是C#分类列表<;TKey,TValue>;。包含抛出null异常的方法是件好事吗?
考虑这段代码(也可用):是C#分类列表<;TKey,TValue>;。包含抛出null异常的方法是件好事吗?,c#,specifications,sortedlist,C#,Specifications,Sortedlist,考虑这段代码(也可用): 使用系统; 使用System.Collections.Generic; 班级计划{ 静态void Main(){ WriteLine(haseItem(new List(),null)); 试一试{ WriteLine(HasItem(new SortedList().Keys,null)); }捕获(异常){ Console.WriteLine(“ArgumentNullException”); } } 公共静态bool HasItem(ICollection集合,字
使用系统;
使用System.Collections.Generic;
班级计划{
静态void Main(){
WriteLine(haseItem(new List(),null));
试一试{
WriteLine(HasItem(new SortedList().Keys,null));
}捕获(异常){
Console.WriteLine(“ArgumentNullException”);
}
}
公共静态bool HasItem(ICollection集合,字符串项){
返回集合。包含(项目);
}
}
问题
输出是
假的
无参数异常
在深入研究了如何工作之后,我发现这个调用相当于调用方法,它有一个ArgumentNullException
文档记录
另一方面,该方法的文档说明:
返回:true
如果在i集合中找到项
;否则,false
在我的示例中,null
不是第二个集合的一部分,因此我希望返回false
。ArgumentNullException
是对接口的违反,因此是一个bug
生产代码中的解决方法是什么?如果属性返回私有泛型嵌套类的实例,并且我没有其他想法,那么类型检查将非常糟糕。另外,类型检查是一种非常讨厌的代码气味。SortedList类实现了
IDictionary
,它指定SortedList
的键、值
性质。由于IDictionary
实现的预期工作方式(利用hashcode对键进行排序或索引),您不能将null
对象作为键输入,因为null
没有有效的hashcode。因此,Contains(…)
方法在尝试将null
传递到参数时将抛出一个ArguementInvalidException
,因为它知道null
不是有效键
如果您想为生产环境“修复”此问题(我不建议这样做,因为这不应该是一个真正的问题),我建议扩展
SortedList
类,并重写Contains(…)
方法,以便在传递null
参数时安全返回。我在MSDN:Type:t上找到这一行
要在集合中定位的对象。对于引用类型,该值可以为null
编辑:您需要System.Linq的using语句
使用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
SortedList temp=新的SortedList();
布尔测试=HasItem(临时键,空);
公共布尔HasItem(ICollection集合,对象项)
{
返回集合。包含(项目);
}//当输入null时,返回false
我认为,通过使用Object作为参数而不是字符串(字符串是不可变的),我的参数可以真正识别为引用类型。无论采用哪种方式,此功能都经过测试并正常工作。祝你好运。我想知道你的问题:-)>在生产代码中有什么解决方法?也有点讨厌,但是捕获异常并返回
false
@Jay谢谢,是的,这是一种可能性,但不幸的是,它太广泛了-我只想处理SortedList
案例catch(ArgumentNullException){return false;}
?我知道,这也很难看。实际上,我会说contains实现是错误的,因为它应该查看值,而不是键。话虽如此,它是什么,它不会改变,所以代码围绕着它。这都是真的,但这也与最初的问题相去甚远。是的,SortedList
是一本字典,好吧,但我们这里说的是SortedList.Keys
,它不是字典,它只是一个集合。另外,我只能访问HasItem
方法,Main
方法是消费者定义的代码哦,但它似乎仍然在同一条船上。不同的包含
方法的状态将利用最适合父对象性质的任何实现(它也明确提到IDictionary
),显然,Keys
属性的实现方式可能类似于ICollection
,但其行为可能更像其父对象IDictionary
。当然,它最终也可能只是一个.NET的怪癖。您是如何编译它的?ICollection
没有Contains(object value)
方法声明我不确定您的意思,但我正在visual studio 2015的asp.net MVC中运行我的代码。我的框架是4.5。您是否在同一个目标框架上运行,这在本例中应该是唯一重要的事情。它编译时没有错误。正如您所看到的,在这个接口中没有这样的方法。您是否100%确定在您的环境中没有为您提供任何扩展方法?好的,我离开并隔离了代码,似乎您需要一个using语句,而您仅仅使用System是无法获得的;使用System.Collections.Generic;您还必须包括System.Linq。但就扩展而言,我编写了很多扩展,但还没有为此编写一个。虽然这确实解决了本例中引发的异常,但代码走的是一条完全不同的道路。如果用户有一个ICollection
的自定义实现,并将其传递给HasItem
方法,该怎么办?您提出的方法不会通过此自定义逻辑。
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