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

老子叫甜甜 提交于 2019-11-30 04:48:47
Guffa

Get the duplicate keys:

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

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.

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

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.

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