web-dev-qa-db-ja.com

null可能な参照型を有効にして引数をnullチェックする場合

C#8.0のnull可能な参照型機能を使用するプログラム内の関数がある場合でも、引数に対してnullチェックを実行する必要がありますか?

void Foo(string s, object o)
{
    if (s == null) throw new ArgumentNullException(nameof(s)); // Do I need these?
    if (o == null) throw new ArgumentNullException(nameof(o));
    ...
}

どのコードもパブリックAPIの一部ではないため、これらのチェックは冗長である可能性があります。 2つのパラメーターはnull可能としてマークされていないため、呼び出しコードがnullで渡される可能性がある場合、コンパイラーは警告する必要があります。

17
Callum Watkins

C#8.0のnull可能な参照型機能を使用するプログラム内の関数がある場合でも、引数に対してnullチェックを実行する必要がありますか?

それはあなたがあなたのAPIを通るすべてのパスをどれだけ確信しているかに依存します。このコードを考えてみましょう:

public void Foo(string x)
{
    FooImpl(x);
}

private void FooImpl(string x)
{
    ...
}

ここでFooImplはパブリックAPIの一部ではありませんが、Fooが検証しない場合itsパラメータ。 (実際、Fooを使用して引数の検証を行っている可能性があります。)

FooImplのチェックインは確かに冗長ではありません実行時にコンパイラーがチェックを実行しているためできないコンパイル時にほぼ確実です。 null可能な参照型は、一般的な安全性を向上させ、さらに重要なのはコードの表現力を向上させますが、CLRが提供する型の安全性とは異なります(たとえば、string参照をType参照として扱うのをやめます。実行時に特定の式がnullであるかどうかのコンパイラーの見方についてコンパイラーが「間違っている」可能性があるさまざまな方法があり、コンパイラーは!でオーバーライドできます。

より広く:チェックが冗長ではなかった場合beforeC#8、チェックは冗長ではありませんafterC#8。null可能参照型機能は、属性の観点以外ではコードに対して生成されたILを変更しないため。

したがって、パブリックAPIが適切なパラメーターチェック(上記の例ではFoo)をすべて実行している場合、コードでのチェックはすでに冗長でした。そのことについてどの程度自信がありますか。あなたが絶対に自信があり、間違っていることの影響が小さい場合、確かに-検証を取り除きます。 C#8の機能はその点で信頼を得るのに役立つかもしれませんが、too自信を得ないように注意する必要があります-結局のところ-コード上記は警告を与えません。

個人的には、C#8のNoda Timeを更新するときにパラメーター検証を削除していません。

18
Jon Skeet