How do you get the duplicate key that ToDictionary() has failed on?

淺唱寂寞╮ 提交于 2019-11-29 02:52:24

问题


I'm creating a Dictionary object, using IEnumerable's ToDictionary() extension method:

var dictionary = new Dictionary<string, MyType>
    (myCollection.ToDictionary<MyType, string>(k => k.Key));

When it executes, it throws the following ArgumentException:

An item with the same key has already been added.

How do I get it to tell me what the duplicate key is?


回答1:


Get the duplicate keys:

var duplicateKeys =
  myCollection
 .GroupBy(k => k.Key)
 .Where(g => g.Count() > 1)
 .Select(g => g.Key);



回答2:


If your specific situation makes it okay to only insert one of a set of objects with duplicate Key properties into your dictionary, you can avoid this error entirely by using the LINQ Distinct method prior to calling ToDictionary.

var dict = myCollection.Distinct().ToDictionary(x => x.Key);

Of course, the above will only work if the classes in your collection override Equals and GetHashCode in a way that only takes the Key property into account. If that's not the case, you'll need to make a custom IEqualityComparer<YourClass> that only compares the Key property.

var comparer = new MyClassKeyComparer();
var dict = myCollection.Distinct(comparer).ToDictionary(x => x.Key);

If you need to make sure that all instances in your collection end up in the dictionary, then using Distinct won't work for you.




回答3:


The failed key is not included because the generic dictionary has no guarantee that there is a meaningful ToString method on the key type. You could create a wrapper class that throws a more informative exception. For example:

//Don't want to declare the key as type K because I assume _inner will be a Dictionary<string, V>
//public void Add(K key, V value)
//
public void Add(string key, V value)
{
    try
    {
        _inner.Add(key, value);
    }
    catch (ArgumentException e)
    {
        throw new ArgumentException("Exception adding key '" + key + "'", e);
    }
}



回答4:


The ArgumentException being thrown by the call to Dictionary.Add doesn't contain the key value. You could very easily add the entries to a dictionary yourself, and do a distinct check beforehand:

    var dictionary = new Dictionary<string, MyType>();
    foreach (var item in myCollection)
    {
        string key = item.Key;
        if (dictionary.ContainsKey(key))
        {
            // Handle error
            Debug.Fail(string.Format("Found duplicate key: {0}", key));
        }
        else
        {
            dictionary.Add(key, item);
        }
    }

This extra check should be fairly inexpensive because elements are stored by hash.



来源:https://stackoverflow.com/questions/5573722/how-do-you-get-the-duplicate-key-that-todictionary-has-failed-on

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!