C# 试题 24:线性集合
0461 以下代码运行结果是什么?
难度: 实战
var list = new List<int> { 1, 2, 3 };
foreach (var x in list)
{
if (x == 2) list.Add(4);
}
- A. 运行抛
InvalidOperationException,枚举期间修改集合 - B. 正常运行,输出 4 个元素
- C. 编译失败
- D. 运行抛
IndexOutOfRangeException
查看答案与解析
正确答案A
解析: List<T> 的枚举器带版本号校验:Add/Remove 等结构修改会使版本号变化,下一次 MoveNext 抛 InvalidOperationException。
关键点: foreach 中不能增删集合;要收集修改请先复制或改用索引循环并自行处理边界。
0462 以下代码输出什么?
难度: 实战
var list = new List<int> { 1, 2, 3, 4, 5 };
list.RemoveAll(x => x % 2 == 0);
Console.WriteLine(string.Join(",", list));
- A.
1,2,3,4,5 - B.
2,4 - C.
1,3,5 - D.
1,2,3
查看答案与解析
正确答案C
解析: RemoveAll(predicate) 原地删除所有满足条件的元素(2、4),保留 1,3,5;它返回删除个数但本例未接收。
关键点: 批量按条件删除用 RemoveAll,它会保持剩余元素的相对顺序。
0463 以下代码输出什么?
难度: 进阶
List<int> list = [1, 2, 3];
Console.WriteLine(list.Count + " " + list.Capacity);
- A.
3 4 - B.
3 3,集合表达式通过List<T>.Create直接按元素数创建 - C.
3 8 - D.
3 0
查看答案与解析
正确答案B
解析: 集合表达式 [1, 2, 3] 借助 [CollectionBuilder] 特性调用 List<T>.Create,创建时容量直接按元素数 3 初始化,不经过逐个 Add 的默认扩容路径。
关键点: 集合表达式与 new List<int> { 1, 2, 3 } 的构造路径不同,初始容量也不同。
0464 以下代码输出什么?
难度: 实战
var list = new List<int> { 1, 2, 3 };
list.Insert(0, 9);
list.RemoveAt(2);
Console.WriteLine(string.Join(",", list));
- A.
9,1,2 - B.
9,2,3 - C.
1,2,3 - D.
9,1,3
查看答案与解析
正确答案D
解析: Insert(0, 9) 得到 [9,1,2,3];RemoveAt(2) 删除下标 2 的元素(2),剩下 [9,1,3]。中间位置插入/删除都会平移后续元素。
关键点: Insert/RemoveAt 是 O(n) 平移操作,下标要按当前集合状态计算。
0465 以下代码输出什么?
难度: 实战
var list = new List<int> { 1, 2, 1 };
bool removed = list.Remove(1);
Console.WriteLine(removed + " " + string.Join(",", list));
- A.
True 2,1,只移除第一个匹配项 - B.
True 1,2 - C.
False 1,2,1 - D.
True 1,1
查看答案与解析
正确答案A
解析: Remove(value) 只移除第一个等于该值的元素并返回是否移除;这里删除第一个 1,集合变为 [2,1]。
关键点: Remove 是按值删一个,RemoveAll 才按条件删全部。
0466 以下代码输出什么?
难度: 实战
var list = new LinkedList<int>();
list.AddLast(1);
list.AddLast(2);
list.AddFirst(0);
Console.WriteLine(string.Join(",", list));
- A.
1,2,0 - B.
2,1,0 - C.
0,1,2 - D.
1,0,2
查看答案与解析
正确答案C
解析: AddLast 追加到尾部,AddFirst 插入头部:先 1,2 后头插 0,得到 0,1,2。
关键点: LinkedList 的“首/尾”操作都是 O(1),枚举按链表顺序。
0467 以下代码输出什么?
难度: 进阶
var list = new LinkedList<int>();
list.AddLast(1);
list.AddLast(2);
list.AddLast(3);
var node = list.Find(2);
list.Remove(node);
Console.WriteLine(string.Join(",", list));
- A.
1,2,3 - B.
1,3 - C.
2 - D. 运行抛异常
查看答案与解析
正确答案B
解析: Find 返回第一个值为 2 的 LinkedListNode<int>,Remove(node) 直接摘下该节点(O(1)),剩下 1,3。
关键点: 持有节点时删除是 O(1);但 Find 本身是 O(n) 线性查找。
0468 关于 LinkedList<T> 的操作复杂度,哪项正确?
难度: 进阶
- A. 按索引访问
list[5]是 O(1) - B.
Contains是 O(1) - C.
AddLast需要遍历整个链表 - D. 持有节点时插入/删除是 O(1),但按值查找
Contains/Find是 O(n),且不支持按下标访问
查看答案与解析
正确答案D
解析: LinkedList<T> 是双向链表:已知节点增删 O(1),首尾操作 O(1);但它没有索引器,Contains/Find 必须线性遍历 O(n)。
关键点: 链表换来的是“任意位置插入删除”,代价是“没有随机访问”。
0469 以下代码输出什么?
难度: 实战
var q = new Queue<int>();
q.Enqueue(1);
q.Enqueue(2);
q.Enqueue(3);
Console.WriteLine(q.Dequeue());
Console.WriteLine(q.Peek());
- A.
1和2 - B.
3和3 - C.
1和1 - D.
3和2
查看答案与解析
正确答案A
解析: Queue<T> 是先进先出:第一次 Dequeue 出队队首 1;Peek 只看不删,返回新的队首 2。
关键点: Peek 不改变队列,Dequeue 才移除元素。
0470 以下代码运行结果是什么?
难度: 实战
var q = new Queue<int>();
q.Dequeue();
- A. 返回
0 - B. 返回
null - C. 运行抛
InvalidOperationException - D. 运行抛
IndexOutOfRangeException
查看答案与解析
正确答案C
解析: 空队列执行 Dequeue/Peek 抛 InvalidOperationException(“队列为空”);要安全出队用 TryDequeue。
关键点: 队列/栈的“取空”都是 InvalidOperationException,不是返回默认值。
0471 以下代码输出什么?
难度: 实战
var s = new Stack<int>();
s.Push(1);
s.Push(2);
s.Push(3);
Console.WriteLine(s.Pop());
Console.WriteLine(s.Peek());
- A.
1和2 - B.
3和2 - C.
3和1 - D.
2和3
查看答案与解析
正确答案B
解析: Stack<T> 是后进先出:Pop 弹出栈顶 3,Peek 返回新的栈顶 2 且不弹出。
关键点: 栈顶是“最后压入”的元素,与队列的方向相反。
0472 以下代码运行结果是什么?
难度: 实战
var s = new Stack<int>();
s.Pop();
- A. 返回
0 - B. 返回
null - C. 运行抛
IndexOutOfRangeException - D. 运行抛
InvalidOperationException
查看答案与解析
正确答案D
解析: 空栈 Pop/Peek 抛 InvalidOperationException;TryPop 才是失败返回 false 的安全版本。
关键点: 空栈操作与空队列一样抛 InvalidOperationException。
0473 以下代码输出什么?
难度: 进阶
var s = new Stack<int>(new[] { 1, 2, 3 });
Console.WriteLine(string.Join(",", s));
- A.
3,2,1,栈从栈顶开始枚举 - B.
1,2,3 - C.
1,3,2 - D. 枚举顺序未定义
查看答案与解析
正确答案A
解析: Stack<T> 的枚举按“栈顶到栈底”的顺序:最后压入的 3 先出现,输出 3,2,1。用集合初始化的栈,枚举顺序与数组顺序相反。
关键点: 栈的枚举天然 LIFO,和 Queue<T> 的 FIFO 枚举方向相反。
0474 以下代码输出什么?
难度: 实战
var list = new List<int>(100);
list.Add(1);
list.Add(2);
list.Clear();
Console.WriteLine(list.Count + " " + list.Capacity);
- A.
0 0 - B.
2 100 - C.
0 100,Clear清空元素但保留容量 - D.
0 4
查看答案与解析
正确答案C
解析: Clear() 把 Count 置 0,但内部数组与 Capacity 不变(仍是 100);后续 Add 不会立即扩容。
关键点: Clear 只重置逻辑长度,不释放已分配的内存。
0475 以下代码输出什么?
难度: 进阶
var list = new List<int>(1000);
list.Add(1);
list.Add(2);
list.TrimExcess();
Console.WriteLine(list.Capacity);
- A.
1000 - B.
2,TrimExcess把容量收缩到接近Count - C.
4 - D.
0
查看答案与解析
正确答案B
解析: TrimExcess 把内部数组收缩到与元素数匹配(通常就是 Count),释放多余预留;本例 Capacity 变为 2。
关键点: 大容量小元素时用 TrimExcess 省内存,代价是下次扩容要重新分配。
0476 以下代码运行结果是什么?
难度: 实战
var list = new List<int> { 1 };
Console.WriteLine(list[3]);
- A. 返回
0 - B. 运行抛
IndexOutOfRangeException - C. 返回
1 - D. 运行抛
ArgumentOutOfRangeException
查看答案与解析
正确答案D
解析: List<T> 索引器越界抛 ArgumentOutOfRangeException(参数校验),与数组访问的 IndexOutOfRangeException 不同。
关键点: 同为越界,List 与数组的异常类型不一样。
0477 以下代码输出什么?
难度: 进阶
var q = new Queue<int>(new[] { 1, 2, 3 });
Console.WriteLine(string.Join(",", q));
- A.
1,2,3,队列从队首开始枚举 - B.
3,2,1 - C.
1,3,2 - D. 枚举顺序未定义
查看答案与解析
正确答案A
解析: Queue<T> 的枚举按“队首到队尾”,即入队顺序:1,2,3。与 Stack<T> 的 LIFO 枚举方向相反。
关键点: 队列枚举 FIFO、栈枚举 LIFO,构造自同一数组时输出顺序相反。
0478 以下代码输出什么?
难度: 实战
var q = new Queue<int>();
Console.WriteLine(q.TryDequeue(out int x));
Console.WriteLine(x);
- A.
True 0 - B.
False,随后抛异常 - C.
False 0,TryDequeue失败时 out 参数为默认值 - D.
True -1
查看答案与解析
正确答案C
解析: 空队列 TryDequeue 返回 false 且不抛异常,out x 被置为默认值 0。
关键点: Try* 家族(TryDequeue/TryPop/TryPeek)失败不抛异常,out 为默认值。
0479 关于 List<T> 的容量(Capacity),哪项正确?
难度: 进阶
- A. 每次
Add都重新分配内部数组 - B. 容量不足时按当前实现大致翻倍扩容;
Count是元素个数,Capacity是内部数组长度,恒有Capacity >= Count - C.
Capacity与Count永远相等 - D. 扩容不会拷贝旧元素
查看答案与解析
正确答案B
解析: Count 是逻辑元素数,Capacity 是内部数组容量;空间不足时分配更大的数组并拷贝旧元素(当前实现大致翻倍)。频繁 Add 的性能取决于预留是否合理。
关键点: 预估规模时用带容量的构造函数,可减少扩容次数;Capacity 不是元素数。
0480 关于 C# 12 集合表达式 [1, 2, 3],哪项正确?
难度: 进阶
- A. 只能赋给数组
- B. 一定编译为逐元素
Add调用 - C. 展开后总是
List<int> - D. 编译器根据目标类型选择创建方式:数组、集合类型或集合 builder(如
List<T>.Create),可避免逐元素扩容
查看答案与解析
正确答案D
解析: 集合表达式是“按目标类型翻译”的语法:目标是数组则直接建数组,目标是实现了集合接口的类型则走 CollectionBuilder 或 Add 路径;List<T> 自带 builder,能按元素数直接创建。
关键点: [...] 是编译器特性不是运行时对象,具体形态由目标类型决定。