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?
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.
来源:https://stackoverflow.com/questions/5573722/how-do-you-get-the-duplicate-key-that-todictionary-has-failed-on