C#面试题更新 2026-08-03

请说明在 C# 中设计一个自定义集合类时,如何让它能够支持 LINQ 查询操作,具体需要实现哪些接口或方法?

考察说明

考查对 LINQ 查询机制以及自定义集合扩展方式的理解。

回答思路

  1. 【回答框架 1】自定义集合类支持 LINQ 查询的核心是实现 System.Collections.Generic.IEnumerable<T> 接口,其中 GetEnumerator 方法返回一个 IEnumerator<T>,使得集合可被 foreach 遍历,并使 LINQ 的扩展方法(如 Where、Select)能够基于该枚举器工作。
  2. 【回答框架 2】若需要提供自定义的查询行为(如延迟执行、索引访问),可以进一步实现 ICollection<T> 或 IList<T> 接口,这些接口继承自 IEnumerable<T>,同时可提供 Count、Add、Remove 等方法。
  3. 【回答框架 3】除了接口实现,还可以通过定义扩展方法(如在静态类中为自定义集合添加 Where 或 Select 方法)来增加专用的查询功能,但通常更推荐直接实现 IEnumerable<T> 以复用标准 LINQ 操作符。
  4. 【回答框架 4】当集合是数组或 List<T> 时,LINQ 查询会利用其内部优化;对于自定义类,应确保 GetEnumerator 的实现正确,并且若集合可变,需注意延迟执行期间对集合的修改可能导致异常或意外结果。
  5. 【回答框架 5】在实现时,可使用 yield return 来简化枚举器的编写,这能自动处理状态机,但需留意在迭代过程中修改集合的风险,以及线程安全方面的考虑。
  6. 【关键点 1】实现 IEnumerable<T> 接口是支持 LINQ 查询的基础。
  7. 【关键点 2】自定义集合通常不需要实现 IQueryable,除非需要外部查询提供程序。
  8. 【关键点 3】使用 yield return 可简化 GetEnumerator 的实现。
  9. 【关键点 4】LINQ 查询默认是延迟执行的,修改集合可能引发异常。
  10. 【关键点 5】实现扩展方法可添加自定义的查询操作。
  11. 【易错点 1】不实现 IEnumerable<T> 而仅实现 IEnumerable,会导致 LINQ 的泛型扩展方法无法直接使用,需进行类型转换。
  12. 【易错点 2】在 GetEnumerator 中返回 null 或错误的枚举器可能导致运行时错误。
  13. 【易错点 3】延迟执行期间修改集合(如增删元素)可能引发 InvalidOperationException。