2015-01-26 66 views
0

我有一個由一些較大的配置文件填充的項目列表。查找在ToDictionary中拋出異常的元素的最佳方法()

List<TextEntrtry> localTextEntries; 

類型TEXTENTRY的元素:

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

該列表被轉換爲一個字典:

Dictionary<Guid, TextEntry> textEntries; 

和這條線拋出異常 '元素具有相同的密鑰已經存在':

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

顯然,我的列表包含兩個具有相同ID的元素。

我的問題:找出哪些元素導致異常的最佳方法是什麼?

(這讓我產生meaningfull錯誤消息)在您的收藏

+0

你不能檢查調試嗎? – 2015-01-26 20:32:52

+0

其中是將此列表轉換爲字典的代碼? – evilone 2015-01-26 20:33:38

+0

@evilone查看我的最後一個代碼片段:'localTextEntries.ToDictionary()' – DrKoch 2015-01-26 20:37:28

回答

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,它將該密鑰存儲爲屬性,而不是在異常消息中包含該密鑰的字符串值(如果該對象沒有良好的字符串表示形式) 。

+0

@stuartd對,謝謝。 – Servy 2015-01-26 21:35:36

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

您可以使用group by來檢查重複或不重複的項目。要創建字典上的分組的項目運行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()); 
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; 
}