Да, есть веские причины:
- Он точно определяет, что является нулем, что может быть неочевидно из
NullReferenceException
- Это приводит к сбою кода при неверном вводедаже если какое-то другое условие означает, что значение не разыменовано
- Это исключение возникает за до , у метода могут быть любые другие побочные эффекты, которые могут возникнуть до первой разыменования
- Это означает, что вы можете быть уверены, что если вы передадите параметр во что-то другое, вы не нарушите их контракт
- Он документирует требования вашего метода (используя Code Contracts еще лучше для этого, конечно)
Теперь что касается ваших возражений:
- Это медленнее : Вы нашли это для на самом деле быть узким местом в вашем коде, или вы догадываетесь?Нулевые проверки очень быстрые, и в подавляющем большинстве случаев они , а не станут узким местом
- Это затрудняет поддержку кода : я думаюпротивоположный.Я думаю, что проще использовать код, когда он становится кристально ясным, может ли параметр быть нулевым или нет, и вы уверены, что это условие выполняется.
И дляВаше утверждение:
Очевидно, что код, который использует s, все равно выдаст исключение.
Правда?Рассмотрим:
void f(SomeType s)
{
// Use s
Console.WriteLine("I've got a message of {0}", s);
}
Использует s
, но не выдает исключение.Если для s
недопустимо быть нулевым, и это означает, что что-то не так, исключение является наиболее подходящим поведением здесь.
Теперь , где вы поставили эти проверки правильности аргументов, это другой вопрос.Вы можете решить довериться всему коду внутри своего класса, поэтому не стоит беспокоиться о частных методах.Вы можете решить доверить остальной части вашей сборки, так что не беспокойтесь о внутренних методах.Вы почти наверняка должны проверить аргументы для открытых методов.
Примечание: перегрузка конструктора с одним параметром ArgumentNullException
должна быть просто именем параметра, поэтому ваш тест должен быть:
if (s == null)
{
throw new ArgumentNullException("s");
}
В качестве альтернативы вы можете создать метод расширения, позволяющий несколько более кратко:
s.ThrowIfNull("s");
В моей версии (универсального) метода расширения я заставляю его возвращать исходное значение, если оно не равно нулю, что позволяет вамнаписать что-то вроде:
this.name = name.ThrowIfNull("name");
Вы также можете иметь перегрузку, которая не принимает имя параметра, если вы не слишком обеспокоены этим.