如何获得ToDictionary()失败的重复键?

时间:2011-04-06 22:25:59

标签: c# dictionary duplicates

我正在使用IEnumerable的{​​{1}}扩展方法创建一个Dictionary对象:

ToDictionary()

执行时会抛出以下var dictionary = new Dictionary<string, MyType> (myCollection.ToDictionary<MyType, string>(k => k.Key));

  

已添加具有相同键的项目。

如何让它告诉我重复的密钥是什么?

4 个答案:

答案 0 :(得分:16)

获取重复的密钥:

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

答案 1 :(得分:8)

如果您的特定情况可以仅将一组具有重复Key属性的对象插入到字典中,则可以在调用之前使用LINQ Distinct方法完全避免此错误ToDictionary

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

当然,只有当您的集合中的类以仅考虑Equals属性的方式覆盖GetHashCodeKey时,上述内容才有效。如果情况并非如此,则您需要制作仅与IEqualityComparer<YourClass>属性进行比较的自定义Key

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

如果您需要确保收藏中的所有实例最终都在字典中,那么使用Distinct将不适合您。

答案 2 :(得分:5)

未包含失败的密钥,因为通用字典无法保证密钥类型上存在有意义的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);
    }
}

答案 3 :(得分:1)

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

这个额外的检查应该相当便宜,因为元素是通过哈希存储的。