C#中Enumerable方法本质是System.Linq.Enumerable类为IEnumerable定义的静态扩展方法,非接口成员;需using System.Linq才可见,且Where延迟执行而First等立即执行,传入不可重用序列时易出错。

直接说结论:C# 中没有所谓“Enumerable 方法大全”这种官方清单,所有你能调用的 Where、Select、OrderBy 等方法,本质都是 System.Linq.Enumerable 类为 IEnumerable<t></t> 定义的静态扩展方法——它们不是接口成员,也不在你写的类里,而是靠 using System.Linq 和编译器的扩展方法查找机制“挂上去”的。
为什么 Intellisense 能看到 Where 却找不到定义位置
你在 List<int></int> 后面输入点号,看到 Where,但按 F12 跳转却可能跳到一个空的扩展方法声明(或提示“未找到源”),这是因为:
-
System.Linq.Enumerable是 .NET 运行时内置类型,其源码不随 SDK 一起分发(除非你装了 .NET Source Link 或反编译) - VS 的 IntelliSense 是通过元数据(
System.Core.dll或System.Linq.dll中的 IL)推导出可用扩展方法的,不是靠你本地代码索引 - 如果你没写
using System.Linq;,这些方法根本不会出现在补全列表里——这不是 bug,是设计使然
Where 和 First 的执行时机差异很关键
看似都是筛选,但行为完全不同:
-
Where返回IEnumerable<t></t>,延迟执行:调用时不查数据,只记下条件;真正触发执行的是foreach、ToList()、ToArray()这类“消费动作” -
First、Single、Count、Average等属于“立即执行”方法:一调用就遍历源序列,哪怕只取第一个匹配项也得从头开始找(除非底层是List<t></t>且做了优化) - 误把
Where当成即时过滤,然后反复调用它去查同一个集合,会导致重复遍历——比如data.Where(x => x > 10).Count()和data.Where(x => x > 10).Any()各走一遍源数据
自定义扩展方法必须严格遵循签名模式
想加个 Median 或 Batch,不能随便写个静态方法就完事:
- 必须是
static class里的static方法,且第一个参数带this IEnumerable<t> source</t> - 泛型约束要合理:比如
Median应该限定T : IComparable<t></t>或直接针对double/int重载,否则运行时OrderBy会炸 - 空值检查不能省:
if (source is null)得放在最前面,否则source.Any()本身就会抛NullReferenceException - C# 14 的 extension 块写法(
extension(IEnumerable<double> source) { ... }</double>)虽简洁,但目前仅支持单类型参数,复杂场景仍得用传统static class
最容易被忽略的是:所有标准 Enumerable 方法都假设输入序列是“可多次枚举”的。如果传入的是 StreamReader.ReadLine() 这种一次性流式数据,Where + Count 组合会失败——因为第二次枚举时流已耗尽。这种边界情况,文档不提,示例不覆盖,只能靠你读源码注释或踩坑后翻 GitHub 上的 dotnet/runtime issue。


















