考虑这段代码(也可用in Ideone):
using System;
using System.Collections.Generic;
class Program {
static void Main() {
Console.WriteLine(HasItem(new List<string>(), null));
try {
Console.WriteLine(HasItem(new SortedList<string, int>().Keys, null));
} catch (ArgumentNullException) {
Console.WriteLine("ArgumentNullException");
}
}
public static bool HasItem(ICollection<string> collection, string item) {
return collection.Contains(item);
}
}
输出
假
ArgumentNullException
在深入了解SortedList<TKey, TValue>
如何工作后,我发现此调用等同于调用SortedList<TKey, TValue>.ContainsKey(TKey key)
方法,该方法记录了ArgumentNullException
。
另一方面,ICollection<T>.Contains
方法的文档说明:
如果在
true
中找到了项目,则返回ICollection<T>
;否则,false
。
好吧,null
不是我示例中第二个集合的一部分,所以我希望返回false
。 ArgumentNullException
违反了界面,因此也是一个错误。
生产代码中的解决方法是什么?鉴于.Keys
属性返回私有通用嵌套类的实例,类型检查将非常难看,我没有任何其他想法。另外,类型检查是一种非常讨厌的代码味道。
答案 0 :(得分:1)
SortedList
类实现了IDictionary
,它指定了Key, value
的{{1}}性质。由于预期SortedList
实现的工作方式(利用哈希码对键进行排序或索引),您无法输入IDictionary
对象作为键,因为null
没有有效的哈希码。因此,null
方法在尝试将Contains(...)
传递给参数时会抛出ArguementInvalidException
,因为它知道null
不是有效密钥。
如果你想为生产环境“解决”这个问题(我不建议,因为这不应该是一个问题),我建议扩展null
类并覆盖{{ 1}}传递SortedList
争论时安全返回的方法。
答案 1 :(得分:-2)
我在MSDN上找到了这一行:输入:T 要在Collection中找到的对象。对于引用类型,该值可以为null。
编辑:您需要使用System.Linq的
语句使用System.Linq;
SortedList<string, int> temp = new SortedList<string, int>();
bool test = HasItem(temp.Keys, null);
public bool HasItem(ICollection<string> collection, object item)
{
return collection.Contains(item);
}//This returns false when fed a null
我认为使用Object作为我的参数而不是字符串是不可变的我的参数真正被识别为引用类型。无论哪种方式,此功能已经过测试并且有效。祝你好运。