C#中Linq GroupBy调用Sum方法时出现类型转换报错
问题根因
这个报错和Sum本身的求和逻辑无关,是两个问题导致的:
- 你将匿名类型生成的强类型集合声明为
IEnumerable<dynamic>,后续所有LINQ操作都会丢失编译期类型检查,调用Sum()时动态绑定逻辑错误匹配了返回int的重载,最终尝试把decimal类型的求和结果隐式转换为int时触发类型不匹配错误。 - 计算
hist_angsuran的三目分支存在逻辑错误:Decimal.Parse(line.Substring(141, 13) + 1)中,Substring返回的是字符串,和整数1做+运算会直接执行字符串拼接,相当于在截取的13位字符串末尾多拼接一个"1"再转decimal,完全不符合「解析后数值加1」的预期。
修复方案
- 移除类级别的
private IEnumerable<dynamic> histix声明,在方法内直接用var接收文件解析生成的集合,让编译器自动推断匿名类型的强类型,从根源上避免动态绑定的重载匹配错误。 - 修正
hist_angsuran的计算逻辑,把+1的数值运算放到Decimal.Parse()括号外部,避免字符串拼接。 - Sum方法不需要做任何int类型转换,类型修正后编译器会自动匹配decimal版本的Sum重载,直接返回decimal类型的求和结果,完全不会出现数值超出int范围的问题。
- 建议把Sum lambda的参数名和外层Select的参数名做区分,避免同名导致的可读性下降。
修复后的完整代码如下:
public void CreateADKTran() { // 用var接收,自动推断为强类型匿名集合 var histix = File.ReadLines(PATH_LNHISTIX) .Skip(1) .Where(line => line.Substring(157, 3) == "PKK" && Decimal.Parse(line.Substring(141, 16)) != 0 && line.Substring(80, 1) != "*" && (line.Substring(58, 1) == "6" || line.Substring(58, 3) == "310")) .Select(line => new { hist_acct_no = line.Substring(0, 10), hist_tran_date = DateTime.ParseExact(line.Substring(61, 8), "yyyyMMdd", provider), hist_outstanding = Decimal.Parse(line.Substring(89, 13)), // 修正+1位置,在数值层面做加法 hist_angsuran = (Decimal.Parse(line.Substring(102, 2)) + Decimal.Parse(line.Substring(154, 2))) >= 100 ? Decimal.Parse(line.Substring(141, 13)) + 1 : Decimal.Parse(line.Substring(141, 13)), hist_txn_code = line.Substring(58, 3), hist_txn_type = line.Substring(58, 1) }); var histixSum = histix.GroupBy(x => new { x.hist_acct_no, x.hist_tran_date, x.hist_txn_type }) .Select(x => new { histAcctno = x.Key.hist_acct_no, histTranDate = x.Key.hist_tran_date, histTxnType = x.Key.hist_txn_type, histOS = x.Last().hist_outstanding, // Sum自动识别decimal类型,直接返回decimal结果 histAngsuran = x.Sum(item => item.hist_angsuran), histTxnCode = x.Last().hist_txn_code }); }
注:原代码中多处
Substring()后额外调用ToString()属于冗余写法,Substring()本身返回值就是字符串类型,可以直接使用。
内容的提问来源于stack exchange,提问作者Anthony Pangestu
相关产品推荐
相关产品推荐

