返回题库高级 .NET 刷题C# 选择题 · 第 23 / 50 篇

C# 试题 23:集合接口

0441 以下代码输出什么?

难度: 实战

int count = 0;
IEnumerable<int> e = Enumerable.Range(0, 3)
    .Select(x => { count++; return x; });

e.Count();
e.Count();
Console.WriteLine(count);
  • A. 3
  • B. 4
  • C. 6,每次 Count() 都从头重新执行查询
  • D. 0
查看答案与解析

正确答案C

解析: LINQ 查询是惰性执行:两次 Count() 各自完整枚举一次,选择器分别执行 3 次,副作用计数累计为 6。

关键点: IEnumerable 不缓存结果,多次枚举等于多次执行,副作用会叠加。

0442 以下代码输出什么?

难度: 进阶

IEnumerable<int> e = new List<int> { 1, 2, 3 };
((List<int>)e).Add(4);

Console.WriteLine(e.Count());
  • A. 4,接口只约束通过接口的访问,下转后可修改原对象
  • B. 3
  • C. 运行抛 InvalidCastException
  • D. 编译失败
查看答案与解析

正确答案A

解析: 接口类型只约束“通过这个接口能做什么”,底层对象仍是 List<int>;下转成功后 Add 直接修改原集合,枚举能看到新元素。

关键点: “IEnumerable 就是只读”是误解,它只代表“可枚举”。

0443 以下代码输出什么?

难度: 实战

IEnumerable<int> Get()
{
    yield return 1;
    yield break;
    yield return 2;
}

Console.WriteLine(Get().Count());
  • A. 0
  • B. 1
  • C. 2
  • D. 编译失败,yield break 后不能有语句
查看答案与解析

正确答案B

解析: yield break 立即结束迭代器,其后的 yield return 2 永远不会执行(编译期会有不可达代码警告),序列只有 1 个元素。

关键点: yield break 是迭代器的“提前 return”,后面的代码是死代码。

0444 以下代码运行结果是什么?

难度: 实战

ICollection<int> c = new int[3];
Console.WriteLine(c.IsReadOnly);
c.Add(1);
  • A. True,随后正常添加
  • B. False,随后正常添加
  • C. False,随后抛异常
  • D. True,随后 AddNotSupportedException
查看答案与解析

正确答案D

解析: 数组实现了 ICollection<T>,但 IsReadOnly 恒为 true,Add/Remove/Clear 都抛 NotSupportedException;数组大小固定,不能改变元素个数。

关键点: IsReadOnly 为 true 意味着“结构不可变”,可变集合该属性为 false。

0445 以下代码输出什么?

难度: 实战

var set = new HashSet<int> { 1, 2, 3 };
Console.WriteLine(set.Add(2));
Console.WriteLine(set.Add(4));
Console.WriteLine(set.Count);
  • A. FalseTrue4
  • B. TrueTrue5
  • C. FalseFalse3
  • D. TrueFalse4
查看答案与解析

正确答案A

解析: ISet<T>.Add 返回“是否新增”:2 已存在返回 False,4 是新的返回 True;Count 从 3 变为 4。

关键点: HashSet 的 Add 不是 void,返回值携带“是否真的加入”的信息。

0446 以下代码输出什么?

难度: 实战

var a = new HashSet<int> { 1, 2, 3 };
var b = new HashSet<int> { 2, 3, 4 };
a.ExceptWith(b);

Console.WriteLine(string.Join(",", a));
  • A. 1,2,3
  • B. 1,2,3,4
  • C. 1
  • D. 2,3
查看答案与解析

正确答案C

解析: ExceptWith 是原地修改:从 a 中移除所有也出现在 b 里的元素(2、3),剩下 1;它不返回新集合。

关键点: ExceptWith 原地改,Except(LINQ)返回新序列,别混用。

0447 以下代码输出什么?

难度: 进阶

var list = new List<int> { 1, 2, 3 };
IEnumerable<int> e = list.Where(x => x > 1);
list.Add(4);

Console.WriteLine(string.Join(",", e));
  • A. 2,3
  • B. 2,3,4Where 延迟执行,枚举时读取最新集合
  • C. 1,2,3,4
  • D. 4
查看答案与解析

正确答案B

解析: Where 的筛选在枚举时执行:虽然查询在 Add(4) 之前创建,但枚举发生在之后,能看到新元素,结果为 2,3,4

关键点: 延迟执行 = 枚举时才取数据,集合随后变化会影响查询结果。

0448 以下代码输出什么?

难度: 进阶

IReadOnlyList<int> r = new List<int> { 1, 2, 3 };
((List<int>)r).Add(4);

Console.WriteLine(r.Count);
  • A. 3
  • B. 运行抛 InvalidCastException
  • C. 编译失败
  • D. 4IReadOnlyList<T> 只保证通过接口只读,不保证对象不可变
查看答案与解析

正确答案D

解析: IReadOnlyList<T> 只是“只读视图”契约,底层对象仍可能是可变的 List<T>;调用方下转后就能修改,Count 变为 4。

关键点: 只读接口不等于不可变对象,防君子不防小人。

0449 以下代码输出什么?

难度: 进阶

IEnumerable<int> Get()
{
    try
    {
        yield return 1;
    }
    finally
    {
        Console.Write("F");
    }
}

using (var e = Get().GetEnumerator())
{
    e.MoveNext();
}
  • A. 输出 Fusing 结束时调用 Dispose,触发 finally
  • B. 无输出
  • C. 编译失败
  • D. 运行抛异常
查看答案与解析

正确答案A

解析: 迭代器对象实现 IDisposableusing 结束时即使只 MoveNext 了一次,也会调用 Dispose,编译器生成的迭代器随即执行 finally,输出 F

关键点: 提前结束枚举时,finallyDispose 触发,这正是 foreach 能清理资源的原因。

0450 以下代码输出什么?

难度: 进阶

IEnumerable<string> strings = new List<string> { "a" };
IEnumerable<object> objects = strings;

Console.WriteLine(objects.Count());
  • A. 编译失败,IEnumerable<T> 不支持协变
  • B. 运行抛 InvalidCastException
  • C. 1IEnumerable<out T> 协变,string 可隐式转换为 object
  • D. 输出 0
查看答案与解析

正确答案C

解析: IEnumerable<out T> 的类型参数标了 out,支持协变:IEnumerable<string> 可隐式转换为 IEnumerable<object>,枚举得到 1 个元素。注意 IList<T> 等可写接口不协变。

关键点: 只读接口协变、可写接口不变,是接口型变设计的核心。

0451 公开 API 想返回“只读集合”,应如何声明?

难度: 进阶

  • A. 直接返回 List<T>,调用方最方便
  • B. 按调用方需求声明 IReadOnlyList<T>/IReadOnlyCollection<T> 等最小接口;同时注意调用方仍可下转为具体类型修改
  • C. 声明 IEnumerable<T> 永远优于 IReadOnlyList<T>
  • D. 返回数组,数组内容一定不可变
查看答案与解析

正确答案B

解析: 面向接口编程:按实际需要的最小能力声明(要下标用 IReadOnlyList,只要 Count 用 IReadOnlyCollection,只枚举用 IEnumerable)。但下转仍可能修改原对象,所以“只读”不等于“防篡改”。

关键点: 最小接口约束意图,数组与 List 都非真正不可变。

0452 以下代码输出什么?

难度: 实战

var a = new HashSet<int> { 1, 2, 3 };
var b = new HashSet<int> { 3, 4, 5 };
a.SymmetricExceptWith(b);

Console.WriteLine(string.Join(",", a));
  • A. 1,2,3,4,5
  • B. 3
  • C. 1,2
  • D. 1,2,4,5,对称差 = 只出现在其中一个集合里的元素
查看答案与解析

正确答案D

解析: SymmetricExceptWith 原地计算对称差:元素 3 同时存在于两边被移除,剩下 1,2,4,5

关键点: 对称差是“并集减交集”,与 ExceptWith(差集)语义不同。

0453 以下代码输出什么?

难度: 进阶

IReadOnlySet<int> set = new HashSet<int> { 1, 2 };
Console.WriteLine(set.IsSubsetOf(new[] { 1, 2, 3 }));
  • A. TrueIReadOnlySet<T> 自 .NET 5 起存在,HashSet<T> 实现了它
  • B. 编译失败,不存在 IReadOnlySet<T>
  • C. False
  • D. 运行抛异常
查看答案与解析

正确答案A

解析: IReadOnlySet<T> 从 .NET 5 引入,HashSet<T>SortedSet<T> 都实现了它,IsSubsetOf 判断集合是否被另一集合包含。

关键点: 只读集合接口比很多人以为的丰富,IReadOnlySet<T> 不是“只有 Count 和 Contains”。

0454 以下代码输出什么?

难度: 进阶

IList<int> list = new int[3];
list[0] = 5;

Console.WriteLine(list[0] + " " + list.IsReadOnly);
  • A. 5 False
  • B. 0 True
  • C. 5 True,数组的 IList<T> 索引器可写,但 IsReadOnly 为 true
  • D. 运行抛 NotSupportedException
查看答案与解析

正确答案C

解析: 数组实现 IList<T> 时,索引器的 setter 正常工作(可以改元素值),但 IsReadOnly 恒为 true,因为数组长度固定、不能增删元素。

关键点: “只读”指结构不可变(不能增删),不代表元素不可改。

0455 以下代码运行结果是什么?

难度: 实战

var xs = new List<int>();
Console.WriteLine(xs.First());
  • A. 输出 0
  • B. 运行抛 InvalidOperationException
  • C. 运行抛 IndexOutOfRangeException
  • D. 输出 null
查看答案与解析

正确答案B

解析: First() 要求序列至少一个元素,空序列抛 InvalidOperationException;它不会返回默认值,那是 FirstOrDefault 的职责。

关键点: First/单值系列与 OrDefault 系列失败行为不同。

0456 以下代码输出什么?

难度: 进阶

HashSet<int> set = new HashSet<int>();
Console.WriteLine(set is ISet<int>);
Console.WriteLine(set is IReadOnlySet<int>);
  • A. TrueFalse
  • B. FalseTrue
  • C. FalseFalse
  • D. TrueTrueHashSet<T> 同时实现 ISet<T>IReadOnlySet<T>
查看答案与解析

正确答案D

解析: HashSet<T> 实现了 ISet<T>ICollection<T>IReadOnlySet<T>IReadOnlyCollection<T> 等;同一个对象可以同时以读写和只读接口访问。

关键点: 一个类型实现多个接口很常见,“是只读接口的实现”不代表对象不可变。

0457 以下代码输出什么?

难度: 实战

var set = new SortedSet<int> { 3, 1, 2 };
Console.WriteLine(string.Join(",", set));
  • A. 1,2,3SortedSet 按比较器升序枚举
  • B. 3,1,2
  • C. 3,2,1
  • D. 枚举顺序未定义
查看答案与解析

正确答案A

解析: SortedSet<T> 按默认比较器维护有序,枚举输出 1,2,3;而 HashSet<T> 的契约不保证任何枚举顺序。

关键点: 需要有序枚举用 SortedSet,需要顺序保证时不要依赖 HashSet。

0458 以下代码输出什么?

难度: 实战

ICollection<int> c = new List<int> { 1, 2, 3 };
Console.WriteLine(c.IsReadOnly);
c.Remove(2);
Console.WriteLine(c.Count);
  • A. True 2
  • B. False 3
  • C. False 2
  • D. True 3
查看答案与解析

正确答案C

解析: List<T>IsReadOnly 为 false,Remove(2) 按值移除第一个匹配项,Count 从 3 变为 2。

关键点: 可变集合的 IsReadOnly 是 false;Remove 按值删、RemoveAt 按下标删。

0459 关于 ICollection<T>IReadOnlyCollection<T> 的区别,哪项正确?

难度: 进阶

  • A. 两者都保证集合不可变
  • B. ICollection<T> 暴露 Add/Remove/Contains/IsReadOnly 等成员;IReadOnlyCollection<T> 只有 Count 与枚举能力,用于表达“只读视图”意图
  • C. IReadOnlyCollection<T>IEnumerable<T> 少一个成员
  • D. List<T> 只实现了 IReadOnlyCollection<T>
查看答案与解析

正确答案B

解析: ICollection<T> 是“可读写集合”的通用契约(含 IsReadOnly 标记);IReadOnlyCollection<T> 只有 Count,比 IEnumerable<T> 多出“已知元素数”的承诺。

关键点: 接口的“readonly”只描述访问方式,不描述底层对象的可改性。

0460 关于“返回 IEnumerable<T> 就是不可变集合”的说法,哪项正确?

难度: 进阶

  • A. 返回 IEnumerable<T> 后调用方无法修改原集合
  • B. IEnumerable<T> 一定是惰性序列
  • C. IEnumerable<T> 保证最多枚举一次
  • D. 接口类型只约束通过该接口的访问:调用方可下转修改,也可多次枚举,惰性查询还会重复执行
查看答案与解析

正确答案D

解析: IEnumerable<T> 既不防下转修改,也不防多次枚举;列表、数组等内存集合可反复枚举,LINQ 惰性查询每次枚举都会重新执行。它只是“可枚举”的最小契约。

关键点: 返回类型表达意图,不提供“不可变/单次”的运行时保证。

官方资料

当前分类

C# 选择题

查看全部分类 →
  1. 21C# 试题 21:Span 与 Memory20 题
  2. 22C# 试题 22:字符串与文本处理20 题
  3. 23C# 试题 23:集合接口20 题
  4. 24C# 试题 24:线性集合20 题
  5. 25C# 试题 25:Dictionary、HashSet 与相等性20 题
ESC

输入关键词开始搜索