43

拡張メソッドが null インスタンスで呼び出された場合 (拡張メソッドがそれを許可していない場合) にスローするのに最適な例外の種類は何だと思いますか? 拡張メソッドは静的メソッドに過ぎないので、ArgumentNullException であるべきだと主張することもできますが、一方でインスタンス メソッドのように使用されるため、NullReferenceException を使用する方が自然かもしれません。次の例を見てみましょう。

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

このようにして、値パラメーターが null の場合、NullReferenceException がスローされます。

他の例は次のようになります。

public static string ToInvariantString(this IFormattable value, string format)
{
    if (value == null) throw new ArgumentNullException("value");
    return value.ToString(format, CultureInfo.InvariantCulture);
}

編集: いくつかの回答では、拡張メソッドを静的メソッドのように呼び出すことができ、その場合、null 参照例外が間違っていることを指摘しました。これは素晴らしい点であり、実際に私の懸念の 1 つですが、理由はわかりませんそもそも質問でそれを言うのを忘れていました。

また、誰かが NullReferenceException をスローするのは間違っていると指摘しましたが、そうです。メソッドを保護せずに、発生させます (CLR にスローさせます)。

私は ArgumentNullException を支持していると思います (これは私がこれまで使用してきたものです) が、メソッドが使用されるほとんどの場所でより自然に見えるため、少なくとも NullReferenceException に反対する余地があると思います。

4

6 に答える 6

39

一般に、例外が含まれている場合は、拡張メソッドを通常の静的メソッドであるかのように扱う必要があります。この場合、ArgumentNullExceptionをスローする必要があります。

ここでNullReferenceExceptionをスローすることは、いくつかの理由で悪い考えです。

  • null参照は実際には発生しなかったため、参照するのは直感に反します
  • NullReferenceExceptionをスローし、NullReferenceExceptionを発生させると、認識できるほど異なる例外が生成されます(違いを確認する1つの方法は、エラーコードです)。これは、CLRによってスローされる多くの例外に当てはまります。

StackOverflowException (この件に関して私が行った投稿)をいつキャッチできるかを参照してください。

  • 通常のメソッドであるかのように拡張メソッドを呼び出すことは完全に合法です。その場合、私は確かにNullReferenceExceptionを除外するのではなく、代わりにArgumentNullExceptionを除外します。
于 2009-01-20T22:06:46.320 に答える
27

他のすべての回答(これは良い)は別として、一貫性のためにMicrosoftが何をしているのかを見る価値があると思います...そして、Enumerableの拡張メソッドはすべて、私が見る限りArgumentNullExceptionをスローします。

于 2009-01-20T22:52:40.270 に答える
7

拡張メソッドはC#2.0で使用でき、静的メソッドと同じように呼び出すことができるため(拡張メソッドとして使用する必要はありません)、ArgumentNullExceptionを使用する必要があります。

型のメソッドのように見えるからといって、それらがそうである、または常に1つのように呼び出されるという意味ではありません。

于 2009-01-20T22:01:24.413 に答える
3

ユーザーの観点からは、メソッドはインスタンスメソッドのように見え、動作するため、私がそれらの場合、NullReferenceExceptionが発生することが予想されます。

そうは言っても、最初の例のように1つをスローするだけでなく、コードで明示的にどちらか一方をスローすることをお勧めします。

于 2009-01-20T21:59:03.230 に答える
2

ArgumentNullException。インスタンスメソッドであるかのように拡張メソッドを呼び出す必要はありません。通常のメソッドであるかのように呼び出すことができます。その場合、NullReferenceExceptionは完全に正しくありません。

于 2009-01-20T22:01:01.043 に答える