ArgumentNullException или NullReferenceException от метода расширения? - PullRequest
39 голосов
/ 21 января 2009

Что вы считаете лучшим типом исключения для выброса, когда метод расширения вызывается для нулевого экземпляра (где метод расширения не позволяет это)? Поскольку методы расширения представляют собой не что иное, как статические методы, вы можете утверждать, что это должно быть ArgumentNullException, но, с другой стороны, они используются как методы экземпляра, поэтому может быть более естественным использовать исключение NullReferenceException. Давайте возьмем следующий пример:

public static string ToInvariantString(this IFormattable value, string format)
{
    return value.ToString(format, CultureInfo.InvariantCulture);
}

Таким образом, будет выброшено исключение NullReferenceException, если значение параметра равно нулю.

Другой пример будет:

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, так как это кажется более естественным в большинстве мест, где метод будет б.

Ответы [ 5 ]

36 голосов
/ 21 января 2009

В целом, с учетом исключений, вы должны относиться к методу расширения как к обычному статическому методу. В этом случае вы должны сгенерировать исключение ArgumentNullException.

Бросать исключение NullReferenceException здесь - плохая идея по нескольким причинам

  • Нулевая ссылка на самом деле не встречалась, поэтому видеть ее нелогично
  • Если генерировать исключение NullReferenceException и вызывать возникновение исключения NullReferenceException, возникают заметно отличающиеся исключения (Одним из способов увидеть разницу является код ошибки). Это верно для многих исключений, которые выдает CLR.

См. Когда вы можете поймать исключение StackOverflowException (пост, который я написал на эту тему).

  • Вполне законно вызывать метод расширения, как если бы он был обычным методом. В этом случае я бы, конечно, не исключение NullReferenceException, а ArgumentNullException.
25 голосов
/ 21 января 2009

Помимо всех других ответов (которые хороши), я думаю, что стоит посмотреть, что Microsoft делает для согласованности ... и методы расширения в Enumerable all выдают ArgumentNullException, насколько я вижу.

7 голосов
/ 21 января 2009

Так как методы расширения могут использоваться в C # 2.0, и они могут вызываться так же, как статические методы (вы НЕ ДОЛЖНЫ использовать их в качестве методов расширения), вы должны использовать ArgumentNullException.

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

2 голосов
/ 21 января 2009

ArgumentNullException. нет требования вызывать методы расширения, как если бы они были методами экземпляра. Вы можете назвать их, как если бы они были обычными методами. В этом случае NullReferenceException будет полностью некорректным.

1 голос
/ 21 января 2009

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

Тем не менее, я бы предложил бросить одно или другое явно в код, а не просто "происходить", чтобы бросить один, как в вашем первом примере.

...