ArgumentNullException или NullReferenceException из метода расширения?
Что бы вы считали лучшим типом исключения, который должен быть брошен, когда метод расширения вызывается в экземпляре null (где метод расширения не позволяет его)? Поскольку методы расширения - это не что иное, как статические методы, вы можете утверждать, что это должно быть ArgumentNullException, но, с другой стороны, они используются как методы экземпляров, поэтому было бы более естественным использовать исключение NullReferenceException. Возьмем следующий пример:
public static string ToInvariantString(this IFormattable value, string format)
{
return value.ToString(format, CultureInfo.InvariantCulture);
}
Таким образом вызывается исключение NullReferenceException, если параметр значения имеет значение null.
Другой пример:
public static string ToInvariantString(this IFormattable value, string format)
{
if (value == null) throw new ArgumentNullException("value");
return value.ToString(format, CultureInfo.InvariantCulture);
}
EDIT:
В некоторых ответах вы указали, что методы расширения можно вызывать как статический метод, и в этих случаях исключение с нулевой ссылкой было бы неправильным, что является отличным моментом и фактически одной из моих проблем, не уверен, почему я забыл упомянуть об этом в вопросе, в первую очередь.
Кто-то также указал, что неправильно выбрасывать исключение NullReferenceException, и да, это так. Поэтому я не бросаю это, я просто позволяю этому (пусть CLR его бросает), не защищая метод.
Я думаю, что я одобряю ArgumentNullException (это то, что я использовал до сих пор), но я все еще думаю, что по крайней мере есть место для аргументации против исключения NullReferenceException, поскольку оно кажется более естественным в большинстве мест, где этот метод будет б.
Ответы
Ответ 1
В общем случае исключения включают, вы должны рассматривать метод расширения, как если бы это был обычный статический метод. В этом случае вы должны бросить ArgumentNullException.
Бросить исключение NullReferenceException здесь - плохая идея по нескольким причинам.
- Нулевая ссылка на самом деле не возникала, так что просмотр одного является неконтуитивным.
- Бросание исключения NullReferenceException и возникновение исключения NullReferenceException приводят к различным различиям (один из способов увидеть разницу - это код ошибки). Это относится ко многим исключениям, которые бросает CLR.
См. Когда вы можете поймать StackOverflowException (сообщение, которое я сделал по этому вопросу).
- Допустимо законно вызывать метод расширения так же, как если бы это был обычный метод. В этом случае я бы, конечно, не исключал исключение NullReferenceException, а вместо ArgumentNullException.
Ответ 2
Помимо всех других ответов (которые хороши), я думаю, что стоит посмотреть, что делает Microsoft ради согласованности... и методы расширения в Enumerable все бросают ArgumentNullException, насколько я могу видеть.
Ответ 3
Так как методы расширения могут использоваться в С# 2.0, их можно вызвать так же, как и статические методы (вы не должны использовать их в качестве методов расширения), вы должны использовать ArgumentNullException.
Просто потому, что они выглядят как методы в типе, это не значит, что они есть или всегда называются как один.
Ответ 4
С точки зрения пользователя метод выглядит и действует как метод экземпляра, поэтому, если бы я был им, я ожидал увидеть исключение NullReferenceException.
Тем не менее, я бы предложил бросить либо один, либо другой явно в коде вместо того, чтобы просто "совершать" выброс, как в вашем первом примере.
Ответ 5
ArgumentNullException. Нет требования для вызова методов расширения, как если бы они были методами экземпляра. Вы можете назвать их так, как если бы они были обычными методами. В этом случае исключение NullReferenceException будет совершенно неверным.