C#调用ToDictionary报重复键错误时如何定位问题重复键
问题描述
调用ToDictionary方法构造SortedDictionary时抛出异常:An item with the same key has already been added,现有try-catch逻辑仅能拿到通用异常提示,无法定位具体是哪个键重复导致执行失败,相关代码如下:
try { var dict = new SortedDictionary<long, long>(ReturnGetReviewTemplates.ToDictionary(tuple => tuple.Item1.Id, tuple => tuple.Item2.ReviewId)); } catch(Exception e) { string error = e.InnerException.Message; }
可行排查方案
- 分组统计法定位重复键
直接调用ToDictionary会在遇到第一个重复键时直接抛出异常且不携带键信息,可先对所有待处理数据按键分组,筛选出出现次数大于1的键,就是导致异常的重复项:// 提取所有重复键 var duplicateKeys = ReturnGetReviewTemplates .GroupBy(t => t.Item1.Id) .Where(g => g.Count() > 1) .Select(g => g.Key) .ToList(); if (duplicateKeys.Any()) { // 此处打断点或打日志,duplicateKeys中存储的就是所有重复的键值 // 可根据业务需求处理重复项:比如保留第一条数据、合并对应值等 } // 处理完重复项后再构造字典,例如用DistinctBy去重保留首个元素 var dict = new SortedDictionary<long, long>( ReturnGetReviewTemplates .DistinctBy(t => t.Item1.Id) .ToDictionary(t => t.Item1.Id, t => t.Item2.ReviewId) ); - 逐行添加捕获定位
若不想大幅改动原有逻辑,可以放弃直接用ToDictionary,手动循环逐次向字典添加元素,触发异常时可直接获取当前正在添加的重复键:var dict = new SortedDictionary<long, long>(); foreach (var item in ReturnGetReviewTemplates) { long key = item.Item1.Id; long value = item.Item2.ReviewId; try { dict.Add(key, value); } catch (ArgumentException ex) { // 此处断点即可拿到触发异常的重复key,可直接记录到错误日志 throw new Exception($"构造字典失败,重复键为:{key}", ex); } } - 版本适配提示
注意:.NET 6 之前版本的ToDictionary方法抛出的异常不会携带具体重复键信息,只有.NET 6及以上版本的异常消息才会附带重复键值,上述两种手动排查方案不受版本限制,兼容性更好。
内容的提问来源于stack exchange,提问作者Jefferson
相关产品推荐
相关产品推荐

