我正在尝试使用Enumerable.SequenceEqual(x,y)
,因为我预计它会在此基础上发挥作用
Object.Equals(x,y)
方法,如果x或y为null,则返回false;如果两者都为null,则返回true(对于null情况)。
但是,Enumerable.SequenceEqual(x,y)
如果任何参数是空引用则抛出异常,如果给出两个空值则不返回true。
在我的代码中,我经常检查集合相等性,所以我创建了一个模拟序列Object.Equals
行为的方法,但我只是想知道这种默认行为背后的逻辑是什么,并且可能存在一个没有例外的现有方法在nulls?
答案 0 :(得分:4)
好吧,MSDN documentation明确声明它会抛出一个ArgumentNullException
,以防任何一个传入的序列为空。我认为这是为了保持与“标准行为”的一致性,当你试图取消引用它时,一个对象抛出NullReferenceException
。考虑一下:
List<int> foo = null;
foo.SequenceEqual(new List<int>());
这是可以的,因为SequenceEqual
是一个扩展方法,因此可以处理一个空对象,但也会让人感到困惑。据我所知,Linq提供的每种扩展方法都遵循这种行为。此外,您不需要为每个扩展方法处理特殊的null情况(您需要同意合理的行为并添加其他逻辑并维护和测试它)。从框架的角度来看,它说它是非法的,使其更加健壮(针对逻辑错误)并保持一致。我经常使用Linq并且从未遇到过这个问题 - 我只是确保我的所有序列都不为空。减少代码混乱(从代码中删除大量空值检查)。
答案 1 :(得分:2)
检查序列相等性的时间点不是在抛出异常时。它作为参数验证器被提前抛出。考虑方法:
public static bool SequenceEquals<T>(this IEnumerable<T> source, IEnumerable<T> target)
{
// Stuff
}
我们明确需要检查source
和target
是否为空,因为如果其中任何一个是,那么我们不能检查序列是否相等。这是一个不可行的状态,SequenceEquals
的结果应该由可枚举的内容控制,而不是可枚举的状态。如果要包含后者,当返回false
时,调用者将如何知道它是否实际上是因为序列不相等而失败,或者一个或两个可枚举是null
?
如果我们没有在这里抛出ArgumentNullException
,当您尝试访问其中一个NullReferenceException
枚举时,CLR会抛出null
。简单地说Object reference not set to an instance of an object
比The argument <something> cannot be null
更有帮助。
请记住,抛出的异常类型通常是关于为什么抛出异常的最有用指标之一。