Sum扩展方法对含null元素的集合会抛NullReferenceException,需用Where过滤或??0兜底;仅支持数值类型求和,string等非数值类型需转为数值属性;性能上for循环通常优于Sum。

Sum扩展方法对null元素会直接抛异常
只要List里有null,又对引用类型属性调用Sum(),运行时立刻报NullReferenceException。这不是设计缺陷,而是Linq默认不帮你做空值防御——它假设你清楚数据状态。
- 安全做法是先过滤:
list.Where(x => x != null).Sum(x => x.Amount) - 如果属性本身可能为
null(比如decimal?),得用?? 0兜底:list.Sum(x => x?.Amount ?? 0) - 注意
Where在前还是Sum在前:先Where能减少计算量;但若集合很大且null极少,Sum(x => x?.Amount ?? 0)反而更简洁
Sum不能直接用于string或自定义类型字段
Sum()只重载了数值类型(int、double、decimal等)的委托签名。传string.Length这种int属性可以,但传string本身会编译失败。
- 错误写法:
list.Sum(x => x.Name)→ 编译报错:Cannot convert lambda expression to delegate because some of the return types in the block are not implicitly convertible to the delegate return type - 正确写法:
list.Sum(x => x.Name.Length)或list.Select(x => x.Name).Sum()(后者要求Name是int数组之类) - 自定义类型要支持求和,得自己实现
+运算符重载,并确保委托返回类型匹配Sum的泛型约束
性能差异:Sum vs for循环遍历累加
对小列表(Sum()因额外的枚举器开销和委托调用,比裸for慢10%–30%。
- 高频调用场景(如游戏帧更新、实时计算)建议用
for:for (int i = 0; i -
Sum()优势在可读性和链式组合,比如list.Where(...).OrderBy(...).Sum(...),此时别为了微小性能牺牲表达力 - 注意
List<t></t>的Count是O(1),但IEnumerable<t></t>的Sum()会强制枚举全部元素,无法提前退出
浮点数求和的精度陷阱
float和double用Sum()累加时,顺序不同结果可能不同——这不是Bug,是IEEE 754浮点规则决定的。
- 例如:
new List<float> { 1e20f, 1.0f, -1e20f }.Sum()</float>结果是0,而数学上应为1.0f - 关键点:Linq的
Sum()按迭代顺序累加,不重排;需要高精度时改用decimal类型字段,或引入Kahan求和算法 - 数据库查询后用
Sum()再算一次?小心双重精度丢失——最好让SQL Server/PostgreSQL在服务端完成求和


















