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

我正在使用IEnumerableToDictionary()扩展方法创建一个Dictionary对象:

 var dictionary = new Dictionary (myCollection.ToDictionary(k => k.Key)); 

执行时,它会抛出以下ArgumentException

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

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

获取重复键:

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

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

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

当然,只有当集合中的类以仅考虑Key属性的方式覆盖EqualsGetHashCode ,上述操作才有效。 如果不是这种情况,则需要创建仅比较Key属性的自定义IEqualityComparer

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

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

未包含失败的密钥,因为通用字典无法保证密钥类型上存在有意义的ToString方法。 您可以创建一个包装类,该类会抛出更具信息性的exception。 例如:

 //Don't want to declare the key as type K because I assume _inner will be a Dictionary //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); } } 

调用Dictionary.Add抛出的ArgumentException不包含键值。 您可以自己轻松地将条目添加到字典中,并事先进行明确的检查:

  var dictionary = new Dictionary(); 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); } } 

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