在ToDictionary()中查找抛出异常的元素的最佳方法

时间:2015-01-26 20:30:02

标签: c# exception dictionary

我有一个由一些较大的配置文件填充的项目列表。

List<TextEntrtry> localTextEntries;

包含TextEntry类型的元素:

 public class TextEntry
 {
    public Guid Id { get;  set; }
    ....

此列表将转换为字典:

Dictionary<Guid, TextEntry> textEntries;

此行抛出异常&#39;具有相同键的元素已存在&#39;:

 textEntries = localTextEntries.ToDictionary(x => x.Id);

显然我的列表包含两个具有相同Id的元素。

我的问题:找出导致异常的元素的最佳方法是什么?

(这将允许我生成有意义的错误消息)

4 个答案:

答案 0 :(得分:2)

在您的收藏集上运行此选项以获取具有重复条目的收件人:

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)));
}

答案 1 :(得分:2)

您可以重新编写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类型,它将密钥存储为属性,而不是在异常消息中包含密钥的字符串值(如果没有良好的字符串表示形式)对象)。

答案 2 :(得分:0)

您可以使用分组来检查重复或不重复的项目。要创建字典,请在分组的项目上运行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());

答案 3 :(得分:0)

最后@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;
}