如何获得ToDictionary()失败的重复键?
我正在使用IEnumerable
的ToDictionary()
扩展方法创建一个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
属性的方式覆盖Equals
和GetHashCode
,上述操作才有效。 如果不是这种情况,则需要创建仅比较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); } }
这种额外的检查应该相当便宜,因为元素是通过哈希存储的。