Как получить дубликат ключа, на котором не удалось выполнить ToDictionary ()? - PullRequest
18 голосов
/ 07 апреля 2011

Я создаю объект Dictionary, используя IEnumerable ToDictionary() метод расширения:

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

При выполнении он выдает следующее ArgumentException:

Элемент с тем же ключом уже был добавлен.

Как мне узнать, что это за дубликат ключа?

Ответы [ 4 ]

16 голосов
/ 07 апреля 2011

Получить дубликаты ключей:

var duplicateKeys =
  myCollection
 .GroupBy(k => k.Key)
 .Where(g => g.Count() > 1)
 .Select(g => g.Key);
8 голосов
/ 07 апреля 2011

Если ваша конкретная ситуация позволяет вставлять в ваш словарь только один из набора объектов с повторяющимися свойствами Key, вы можете полностью избежать этой ошибки, используя метод LINQ Distinct перед вызовом ToDictionary.

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

Конечно, вышеописанное будет работать только в том случае, если классы в вашей коллекции переопределяют Equals и GetHashCode таким образом, что учитывается только свойство Key.Если это не так, вам нужно создать пользовательский IEqualityComparer<YourClass>, который сравнивает только свойство Key.

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

Если вам нужно убедиться, что все экземпляры в вашей коллекции заканчиваются всловарь, тогда использование Distinct не будет работать для вас.

5 голосов
/ 07 апреля 2011

Ключ с ошибкой не включен, потому что в общем словаре нет гарантии, что для типа ключа имеется значимый метод ToString. Вы можете создать класс-оболочку, который создает более информативное исключение. Например:

//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);
    }
}
1 голос
/ 07 апреля 2011

ArgumentException, выбрасываемый вызовом Dictionary.Add, не содержит значения ключа.Вы можете очень легко добавить записи в словарь самостоятельно и заранее сделать отдельную проверку:

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

Эта дополнительная проверка должна быть довольно недорогой, поскольку элементы хранятся в хэше.

...