查找在 ToDictionary() 中抛出异常的元素的最佳方法
Best method to find element which throws exception in ToDictionary()
我有一个由一些更大的配置文件填充的项目列表。
List<TextEntrtry> localTextEntries;
具有 TextEntry 类型的元素:
public class TextEntry
{
public Guid Id { get; set; }
....
此列表已转换为字典:
Dictionary<Guid, TextEntry> textEntries;
并且此行抛出异常 'Element with same key already exists':
textEntries = localTextEntries.ToDictionary(x => x.Id);
显然我的列表包含两个具有相同 ID 的元素。
我的问题:找出哪些元素导致异常的最佳方法是什么?
(这将允许我生成有意义的错误消息)
运行 在您的 collection 上执行此操作以获取具有重复条目的条目:
var duplicateEntries = localTextEntries.GroupBy(k = > k.Id)
.Where(g = > g.Count() > 1)
.Select(g = > g.Key);
您也可以随时添加扩展方法并从源中获取不同的值
IEnumerable <TextEntry> distinctList = localTextEntries.DistinctBy(x = > x.Id);
public static IEnumerable<TSource> Distinctify<TSource, TKey>(this IEnumerable<TSource> inSrc_, Func<TSource, TKey> keyFunct_)
{
var uniqueSet = new HashSet<TKey>();
return inSrc_.Where(tmp => uniqueSet.Add(keyFunct_(tmp)));
}
您可以重写 ToDictionary
以使用您自己的实现,在异常消息中包含 key
:
//TODO come up with a slightly better name
public static Dictionary<TKey, TValue> MyToDictionary<TSource, TKey, TValue>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TValue> valueSelector,
IEqualityComparer<TKey> comparer)
{
comparer = comparer ?? EqualityComparer<TKey>.Default;
var dictionary = new Dictionary<TKey, TValue>(comparer);
foreach (var item in source)
{
var key = keySelector(item);
try
{
dictionary.Add(key, valueSelector(item));
}
catch (ArgumentException ex)
{
throw new ArgumentException("Missing key: " + key, ex);
}
}
return dictionary;
}
您想创建没有比较器或值选择器的重载,其中使用这些参数的默认值。
您可能还想创建一种新的 Exception
类型,将密钥存储为 属性,而不是在异常消息中包含密钥的字符串值(如果存在不是对象的良好字符串表示形式)。
您可以使用分组依据来检查重复或不重复的项目。要在分组项目上创建字典 运行 ToDictionary
方法:
// get repeated items
var repeated = localTextEntries.GroupBy(t => t.Id).Where(g => g.Count() > 1).Select(i => i);
// get not repeated items
var notRepeated = localTextEntries.GroupBy(t => t.Id).Where(g => g.Count() == 1).Select(i => i.First());
// find not repeated items and create a dictionary
var dictFromNotRepeated = localTextEntries.GroupBy(t => t.Id)
.Where(g => g.Count() == 1)
.ToDictionary(g => g.Key, g => g.First());
最后,@Servy 的方法最适合我。我只是选择了一个匹配的重载并添加了一些更好的错误处理:
public static Dictionary<TKey, TSource> ToDictionary2<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
IEqualityComparer<TKey> comparer = null)
{
comparer = comparer ?? EqualityComparer<TKey>.Default;
Dictionary<TKey, TSource> dictionary =
new Dictionary<TKey, TSource>(comparer);
foreach (var item in source)
{
var key = keySelector(item);
try
{
dictionary.Add(key, item);
}
catch (Exception ex)
{
string msg = string.Format("Problems with key {0} value {1}",
key,
item);
throw new Exception(msg, ex);
}
}
return dictionary;
}
我有一个由一些更大的配置文件填充的项目列表。
List<TextEntrtry> localTextEntries;
具有 TextEntry 类型的元素:
public class TextEntry
{
public Guid Id { get; set; }
....
此列表已转换为字典:
Dictionary<Guid, TextEntry> textEntries;
并且此行抛出异常 'Element with same key already exists':
textEntries = localTextEntries.ToDictionary(x => x.Id);
显然我的列表包含两个具有相同 ID 的元素。
我的问题:找出哪些元素导致异常的最佳方法是什么?
(这将允许我生成有意义的错误消息)
运行 在您的 collection 上执行此操作以获取具有重复条目的条目:
var duplicateEntries = localTextEntries.GroupBy(k = > k.Id)
.Where(g = > g.Count() > 1)
.Select(g = > g.Key);
您也可以随时添加扩展方法并从源中获取不同的值
IEnumerable <TextEntry> distinctList = localTextEntries.DistinctBy(x = > x.Id);
public static IEnumerable<TSource> Distinctify<TSource, TKey>(this IEnumerable<TSource> inSrc_, Func<TSource, TKey> keyFunct_)
{
var uniqueSet = new HashSet<TKey>();
return inSrc_.Where(tmp => uniqueSet.Add(keyFunct_(tmp)));
}
您可以重写 ToDictionary
以使用您自己的实现,在异常消息中包含 key
:
//TODO come up with a slightly better name
public static Dictionary<TKey, TValue> MyToDictionary<TSource, TKey, TValue>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TValue> valueSelector,
IEqualityComparer<TKey> comparer)
{
comparer = comparer ?? EqualityComparer<TKey>.Default;
var dictionary = new Dictionary<TKey, TValue>(comparer);
foreach (var item in source)
{
var key = keySelector(item);
try
{
dictionary.Add(key, valueSelector(item));
}
catch (ArgumentException ex)
{
throw new ArgumentException("Missing key: " + key, ex);
}
}
return dictionary;
}
您想创建没有比较器或值选择器的重载,其中使用这些参数的默认值。
您可能还想创建一种新的 Exception
类型,将密钥存储为 属性,而不是在异常消息中包含密钥的字符串值(如果存在不是对象的良好字符串表示形式)。
您可以使用分组依据来检查重复或不重复的项目。要在分组项目上创建字典 运行 ToDictionary
方法:
// get repeated items
var repeated = localTextEntries.GroupBy(t => t.Id).Where(g => g.Count() > 1).Select(i => i);
// get not repeated items
var notRepeated = localTextEntries.GroupBy(t => t.Id).Where(g => g.Count() == 1).Select(i => i.First());
// find not repeated items and create a dictionary
var dictFromNotRepeated = localTextEntries.GroupBy(t => t.Id)
.Where(g => g.Count() == 1)
.ToDictionary(g => g.Key, g => g.First());
最后,@Servy 的方法最适合我。我只是选择了一个匹配的重载并添加了一些更好的错误处理:
public static Dictionary<TKey, TSource> ToDictionary2<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
IEqualityComparer<TKey> comparer = null)
{
comparer = comparer ?? EqualityComparer<TKey>.Default;
Dictionary<TKey, TSource> dictionary =
new Dictionary<TKey, TSource>(comparer);
foreach (var item in source)
{
var key = keySelector(item);
try
{
dictionary.Add(key, item);
}
catch (Exception ex)
{
string msg = string.Format("Problems with key {0} value {1}",
key,
item);
throw new Exception(msg, ex);
}
}
return dictionary;
}