Почему Перечислимым.SequenceEqual вызывает исключение, если какой-либо параметр равен null?

Я пытался использовать Enumerable.SequenceEqual(x,y) Как я ожидал, он будет работать на основе Object.Equals(x,y) метод, который возвращает false, если x или y равно null, и true, если оба равно null (для нулевых случаев).

Enumerable.SequenceEqual(x,y) создает исключение, если какой-либо параметр является нулевой ссылкой и не возвращает true, если ему задано два нуля.

в моем коде я часто проверяю равенство коллекции, поэтому я создал метод, который имитирует Object.Equals поведение для последовательностей, но мне просто интересно, какова логика такое поведение по умолчанию, и есть ли, возможно, существующий метод без исключений для нулей?

2 ответов


Ну документация MSDN явно указывает, что он бросает ArgumentNullException в случае, если любой из переданных последовательностей равен null. Я предполагаю, что это должно поддерживать согласованность со "стандартным поведением", когда объект бросает NullReferenceException когда вы пытаетесь разыменовать его. Рассматривайте это:

 List<int> foo = null;
 foo.SequenceEqual(new List<int>());

Это было бы хорошо, как SequenceEqual является методом расширения и поэтому может обрабатывать нулевой объект, но это также было бы запутанным. Каждый метод расширения, предоставляемый Linq, следует этому поведение, насколько я знаю. Также вам не нужно обрабатывать специальные нулевые случаи для каждого метода расширения (вам нужно будет согласиться с разумным поведением и добавить дополнительную логику и поддерживать и тестировать ее). Говоря, что это незаконно, делает его более надежным (против логических ошибок) и последовательным с точки зрения фреймворка. Я много использую Linq и никогда не сталкивался с этой проблемой - я просто удостоверяюсь, что все мои последовательности не равны нулю. Уменьшает беспорядок кода (удаляет много нулевых проверок из кода).


точка, в которой он проверяет равенство последовательности, не является, когда это исключение создается. Он выбрасывается ранее в качестве аргумента validator. Рассмотрим метод:

public static bool SequenceEquals<T>(this IEnumerable<T> source, IEnumerable<T> target)
{
    // Stuff
}

нам явно нужно проверить это source и target не являются null, потому что если любой из них, то мы не могу проверьте равенство последовательности. Это неработоспособное состояние, и результат SequenceEquals должны регулироваться содержание enumerables, а не государство из enumerables. Если бы он включал последнее, при возвращении false, как бы вызывающий знал, действительно ли он терпит неудачу, потому что последовательности не равны, или один или оба перечисляемых являются null?

если бы мы не бросили ArgumentNullException здесь CLR бросил бы NullReferenceException при попытке доступа к одному из null enumerables. Просто говоря Object reference not set to an instance of an object гораздо менее полезно, чем The argument <something> cannot be null.

помните, что тип создаваемого исключения как правило, один из самых полезных индикаторов о почему исключение.