自定义SumNotZero方法处理Lambda除法求和仍报DivideByZeroException求助
解决Lambda求和时除数为0的异常问题
问题根源
你遇到的DivideByZeroException无法被自定义SumNotZero方法捕获,大概率是两种情况:
- 集合是ORM的IQueryable(比如EF Core):传入的
x => x.a / x.b会被翻译成SQL在数据库执行,异常在数据库端抛出,根本没进入你方法里的try-catch块。 - 内存集合但DoLog方法抛出异常:如果是内存集合,除法异常本应被捕获,但如果
DoLog本身报错,会掩盖原异常。
针对性解决方案
1. 内存集合(如List)
方案1:调用时提前判断除数
直接在Lambda里判断除数是否为0,避免抛出异常,同时利用你的方法跳过null项:
listDatas.SumNotZero(x => x.b != 0 ? x.a / x.b : null)
这种方式不需要修改SumNotZero方法,性能更优,因为提前规避了异常。
方案2:修改扩展方法,内置除法逻辑
把被除数、除数的选择逻辑分开,在方法内部处理除数为0的情况,避免异常:
public static decimal? SumNotZero<TSource>(this IEnumerable<TSource> source, Func<TSource, decimal> numeratorSelector, Func<TSource, decimal> denominatorSelector) { decimal sum = 0; foreach (var item in source) { try { var denominator = denominatorSelector(item); if (denominator == 0) { DoLog("除数为0,跳过当前项"); continue; } var value = numeratorSelector(item) / denominator; sum += value; } catch (Exception ex) { DoLog($"计算出错:{ex.Message}"); } } return sum; }
调用方式:
listDatas.SumNotZero(x => x.a, x => x.b)
2. ORM查询集合(如EF Core IQueryable)
这种场景下,Lambda会被翻译成SQL,无法在内存中捕获数据库端的异常,需要二选一:
方案A:加载到内存后处理
先把数据拉到内存,再用内存集合的方案:
listDatas.ToList().SumNotZero(x => x.a, x => x.b)
注意:如果数据量很大,这种方式会占用较多内存,需根据业务评估。
方案B:SQL层面规避除数为0
利用EF支持的CASE WHEN语法,让数据库直接处理除数为0的情况,返回null后被Sum忽略:
var sumAB = listDatas.Sum(x => x.b != 0 ? x.a / x.b : (decimal?)null);
这种方式性能最优,但无法记录具体哪些项除数为0,若需要日志,还是得用方案A。
3. 处理Sum(x=>x.c)/Sum(x=>x.a/x.b)这类场景
除了处理每个x.b为0的情况,还要注意分母的求和结果可能为0:
var sumC = listDatas.Sum(x => x.c); var sumAB = listDatas.SumNotZero(x => x.a, x => x.b); // 根据业务需求处理分母为0的情况,这里示例返回0 var result = sumAB.HasValue && sumAB.Value != 0 ? sumC / sumAB.Value : 0;
内容的提问来源于stack exchange,提问作者Wihelm jie
相关产品推荐
相关产品推荐

