用 Find 返回匹配元素,Contains 仅判断存在性;FirstOrDefault 更常用因其语义明确、支持 IEnumerable 链式调用且对可空类型更安全;IndexOf 返回下标但依赖 Equals,自定义类需重写;性能敏感时避免 lambda 捕获变量。

用 Find 还是 Contains?看你要返回啥
查元素不等于“判断有没有”——这是新手最容易混淆的起点。Contains 只返回 true 或 false,底层调用 Equals,适合判断值类型或已重写 Equals 的引用类型;Find 返回匹配的第一个元素(没找到返回默认值),适合要拿数据继续处理的场景。
- 要改匹配项的某个字段?必须用
Find或FirstOrDefault拿到对象引用 - 只校验是否存在且性能敏感?
Contains在List<t></t>上是 O(n),但比Find(x => x.Id == 123)少一次委托调用开销 - 自定义类没重写
Equals?Contains默认比较引用,永远返回false,这时候必须用Any或Find配合 lambda
FirstOrDefault 为什么比 Find 更常用
Find 是 .NET Framework 2.0 就有的老方法,返回 default(T);而 FirstOrDefault 是 LINQ 方法,语义更明确,且在空集合或没匹配时行为一致。更重要的是:它支持所有 IEnumerable<t></t>,不锁死在 List<t></t>。
- 返回值类型相同,但
FirstOrDefault可链式调用其他 LINQ 方法,比如.Where(...).FirstOrDefault() - 对可空值类型(如
int?),Find返回0,FirstOrDefault返回null,语义更安全 - 调试时,
FirstOrDefault的调用栈更清晰,尤其在异步或并行上下文中
用 IndexOf 找位置,但别忘了它只认相等性
IndexOf 返回第一个匹配元素的下标,不是布尔值也不是元素本身。但它底层仍依赖 Equals,所以和 Contains 面临同样的陷阱:自定义类没重写 Equals 就找不到。
- 想删掉某个特定实例?先
IndexOf拿下标,再RemoveAt,比Remove(按值删)更准,避免误删其他相等对象 - 查找失败时返回
-1,别直接当数组索引用,得先判断 - 如果要找多个匹配项的下标,
FindIndex+ 循环或FindAll+Select索引更稳妥,别硬套IndexOf
性能坑:Lambda 捕获变量可能引发意外 GC
写 list.Find(x => x.Name == searchName) 看似没问题,但如果 searchName 是局部变量,每次调用都会生成闭包对象。高频查找(比如 UI 刷新、游戏帧循环)会推高 GC 压力。
- 把 lambda 提成预编译委托:
static readonly Func<item bool> NameMatcher = x => x.Name == "target";</item> - 值类型查找尽量用
Span<t>.IndexOf</t>(.NET 5+),绕过 LINQ 分配 - 大数据量(>10k)且查找频繁?考虑提前建
Dictionary<tkey tvalue></tkey>或HashSet<t></t>,别在线性查找上硬扛


















