71

何らかのオブジェクトを引数として取るメソッドがあるとします。ここで、このメソッドに null 引数が渡された場合、それは致命的なエラーであり、例外がスローされる必要があるとします。このようなコードを作成する価値はありますか (これは些細な例であることを念頭に置いてください)。

void someMethod(SomeClass x)
{
    if (x == null){
        throw new ArgumentNullException("someMethod received a null argument!");
    }

    x.doSomething();
}

それとも、x.doSomething() を呼び出すときに NullException をスローすることに頼っても安全ですか?

次に、 someMethod がコンストラクターであり、別のメソッドが呼び出されるまで x が使用されないとします。すぐに例外をスローするか、x が必要になるまで待ってから例外をスローする必要がありますか?

4

14 に答える 14

68

引数をチェックしないと提供ArgumentNullExceptionされるよりも、私はそれを好みます。NullReferenceException一般に、null の可能性があるオブジェクトでメソッドを呼び出そうとする前に、常に null かどうかをチェックすることを好みます。

メソッドがコンストラクターである場合、それはいくつかの異なる要因に依存します: プロパティのパブリック セッターも存在するか、オブジェクトが実際に使用される可能性はどれくらいか。public セッターがある場合、コンストラクターを介して有効なインスタンスを提供しないことは合理的であり、例外が発生することはありません。

パブリック セッターがなく、挿入されたオブジェクトを参照せずに包含オブジェクトを使用できる場合は、その使用が試行されるまでチェック/例外を延期することをお勧めします。ただし、一般的なケースでは、注入されたオブジェクトはインスタンスの機能に不可欠であり、インスタンスがそれなしでは機能しないため、ArgumentNull 例外は完全に合理的であると思います。

于 2008-12-15T15:46:10.840 に答える
38

私は常にフェイルファストの慣習に従います。メソッドが X に依存していて、X が null で渡される可能性があることを理解している場合は、null チェックを行い、障害点を長引かせる代わりに、すぐに例外を発生させます。

2016 更新:

実世界の例。JetBrains Annotationsの使用を強くお勧めします。

[Pure]
public static object Call([NotNull] Type declaringType, 
                          [NotNull] string methodName, 
                          [CanBeNull] object instance)
{
    if (declaringType == null) throw new ArgumentNullException(nameof(declaringType));
    if (methodName == null) throw new ArgumentNullException(nameof(methodName));

nameofガード ステートメントは、演算子を提供する C# 6 で大幅に改善されました。

于 2008-12-15T15:46:12.243 に答える
15

次の理由から、明示的な例外を好みます。

  • メソッドに複数の SomeClass 引数がある場合、それがどれであるかを示す機会が与えられます (他のすべてはコール スタックで利用可能です)。
  • x を参照する前に副作用があるかもしれないことをしたらどうなるでしょうか?
于 2008-12-15T15:46:57.140 に答える
13

最近チェックしない言い訳はありません。C# は進化しており、破棄と null 合体演算子を使用してこれを非常にうまく行うことができます。

_ = declaringType ?? throw new ArgumentNullException(nameof(declaringType));
_ = methodname ?? throw new ArgumentNullException(nameof(methodName));
于 2020-03-11T10:58:46.363 に答える
12

私は早く失敗するという考えに同意します - しかし、なぜ早く失敗することが実際的であるかを知ることは賢明です. 次の例を検討してください。

void someMethod(SomeClass x)
{       
    x.Property.doSomething();
}

NullReferenceException何かが間違っていたことを伝えるために に頼る場合、何がヌルであったかをどのように知ることができますか? スタック トレースは、どの参照が null であったかではなく、行番号のみを示します。この例ではx、またはx.Property両方が null である可能性があり、事前に積極的なチェックで高速に失敗しなければ、それがどちらであるかはわかりません。

于 2008-12-15T18:28:14.803 に答える
9

明示的な ArgumentNullException を使用したパラメーター チェックも好みます。

メタデータを見る:

 //
    // Summary:
    //     Initializes a new instance of the System.ArgumentNullException class with
    //     the name of the parameter that causes this exception.
    //
    // Parameters:
    //   paramName:
    //     The name of the parameter that caused the exception.
    public ArgumentNullException(string paramName);

文字列はパラメーターの名前である必要があることがわかります。つまり、null であるため、何が問題なのかについて開発者にヒントを与えることができます。

于 2008-12-15T15:50:39.270 に答える
6

入力が null でないことが予想される場合は、ArgumentNullException を明示的にスローする必要があります。このためのヘルパー メソッドを提供する Guard というクラスを作成することをお勧めします。したがって、コードは次のようになります。

void someMethod(SomeClass x, SomeClass y)
{
    Guard.NotNull(x,"x","someMethod received a null x argument!");
    Guard.NotNull(y,"y","someMethod received a null y argument!");


    x.doSomething();
    y.doSomething();
}

NonNull メソッドは nullity チェックを実行し、呼び出しで指定されたエラー メッセージとともに NullArgumentException をスローします。

于 2008-12-15T15:50:35.417 に答える
5

遅かれ早かれ ArgumentNullException をスローすることをお勧めします。これをスローすると、NullReferenceException よりも問題に関する有益な情報を提供できます。

于 2008-12-15T15:48:30.240 に答える
4
  1. Null 値が必要ない場合は、明示的に実行してください。そうしないと、他の誰かがあなたのコードを見たときに、Null 値を渡しても問題ないと思うでしょう。

  2. できるだけ早くそれをしてください。このようにして、想定されていないときに Null を持つという「間違った」動作を広めることはありません。

于 2008-12-15T15:49:07.573 に答える
3

私はおそらくこれに反対票を投じるでしょうが、私は完全に違うと思います。

「null を渡さない」という優れたプラクティスに従い、醜い例外チェックを削除するのはどうでしょうか。

パラメータがオブジェクトの場合は、NULL を渡さないでください。また、NULL を返さないでください。Null オブジェクト パターンを使用して、それを支援することもできます。

オプションの場合は、既定値を使用するか (言語でサポートされている場合)、オーバーロードを作成します。

醜い例外よりもはるかにきれいです。

于 2010-10-05T14:32:58.070 に答える
3

防御的にプログラムすると、すぐに失敗するはずです。そのため、コードの先頭で入力とエラーを確認してください。発信者には親切に対応し、できる限りわかりやすいエラー メッセージを伝えてください。

于 2008-12-15T15:47:20.680 に答える
1

次のような構文を使用しArgumentNullExceptionて、例外をスローするだけでなく、そのエラー テキストの一部としてパラメーターに名前を付けることもできます。例えば;

void SomeMethod(SomeObject someObject)
{
    Throw.IfArgNull(() => someObject);
    //... do more stuff
}

例外を発生させるために使用されるクラスは次のとおりです。

public static class Throw
{
    public static void IfArgNull<T>(Expression<Func<T>> arg)
    {
        if (arg == null)
        {
            throw new ArgumentNullException(nameof(arg), "There is no expression with which to test the object's value.");
        }

        // get the variable name of the argument
        MemberExpression metaData = arg.Body as MemberExpression;
        if (metaData == null)
        {
            throw new ArgumentException("Unable to retrieve the name of the object being tested.", nameof(arg));
        }

        // can the data type be null at all
        string argName = metaData.Member.Name;
        Type type = typeof(T);
        if (type.IsValueType && Nullable.GetUnderlyingType(type) == null)
        {
            throw new ArgumentException("The expression does not specify a nullible type.", argName);
        }

        // get the value and check for null
        if (arg.Compile()() == null)
        {
            throw new ArgumentNullException(argName);
        }
    }
}
于 2017-07-19T16:30:54.457 に答える
0

すべてのコード例では、エラーが発生しやすい IF 句を使用していますが、1 つは equal operator を使用しています==

タイプが override の場合はどうなります==か?

C# 7 以降では、定数パターン マッチングを使用します。

例:

if (something is null) 
{
    throw new ArgumentNullException(nameof(something), "Can't be null.");
}
于 2021-08-11T11:47:19.553 に答える