web-dev-qa-db-ja.com

C#/。NETでパラメーターをNULL不可としてマークしますか?

nullがC#/。NETで渡されないようにする関数パラメーターに割り当てることができる単純な属性またはデータコントラクトはありますか?理想的には、コンパイル時に、リテラルnullがどこにも使用されていないことを確認し、実行時にArgumentNullExceptionをスローします。

現在、私は次のようなものを書いています...

if (null == arg)
  throw new ArgumentNullException("arg");

... nullでないと予想されるすべての引数に対して。

同じメモに、Nullable<>の反対があり、それによって以下が失敗します。

NonNullable<string> s = null; // throw some kind of exception
87

残念ながら、コンパイル時に利用できるものはありません。

少し hacky solution があります。最近ブログに投稿しましたが、新しい構造体と変換を使用しています。

コードコントラクト を使用した.NET 4.0では、人生はずっと良くなります。実際の言語構文と非NULL可能性のサポートがあれば、それでもかなりいいでしょうが、コードコントラクトは大いに役立ちます。

MiscUtil にはThrowIfNullと呼ばれる拡張メソッドもあり、少し簡単になります。

最後のポイント-「if (null == arg)」の代わりに「if (arg == null)」を使用する理由後者の方が読みやすく、前者がCで解決する問題はC#には当てはまりません。

66
Jon Skeet

私はこの質問に信じられないほど遅れていることを知っていますが、C#の最新のメジャーイテレーションがリリースに近づいてからリリースされると、答えが適切になると感じています。 C#8.0では大きな変更が発生し、C#ではallタイプがnullではないと見なされます。

Mads Torgersenによると:

問題は、null参照が非常に役立つことです。 C#では、これらはすべての参照タイプのデフォルト値です。デフォルト値は他に何でしょうか?変数に割り当てる他の値を決定するまで、変数には他にどのような値がありますか?あなたがそれを埋めるまで、新しく割り当てられた参照の配列を他のどのような値で舗装できますか?

また、null自体が賢明な値である場合もあります。たとえば、フィールドに値がないという事実を表したい場合があります。パラメータに「なし」を渡しても構いません。ただし、時には重点が置かれます。そして、ここに問題の別の部分があります。C#のような言語では、ここでnullが良いアイデアであるかどうかを表現できません。

そのため、Madsが概説した解決策は次のとおりです。

  1. 参照がnullにならないようにすることがより一般的であると考えています。 Nullableの参照型はよりまれな種類であるため(どの程度の量を示すのかを示す良いデータはありません)、それらは新しい注釈を必要とするものです。

  2. この言語にはすでに、null許容値型の概念と構文があります。この2つの類似性により、言語の追加が概念的に簡単になり、言語的にも簡単になります。

  3. 自分や自分の消費者に面倒なnull値を与えたいと積極的に決めたのでなければ、面倒なnull値を与えるべきではないようです。ヌルは、それらの不在ではなく、明示的にオプトインする必要があるものでなければなりません。

目的の機能の例:

public class Person
{
     public string Name { get; set; } // Not Null
     public string? Address { get; set; } // May be Null
}

プレビューは、Visual Studio 2017、15.5.4+プレビューで利用できます。

14
Greg

これは非常に古い質問ですが、これはここにありませんでした:

ReSharper/Riderを使用する場合は、 注釈付きフレームワーク を使用できます。

Edit:この回答に対してランダム-1を得ました。それはいいです。 C#8.0 +プロジェクトの推奨アプローチではなくなったにもかかわらず、stillが有効であることに注意してください(理由を理解するには、 グレッグの答え を参照してください) 。

14
rsenna

エンタープライズライブラリーのバリデーターを確認してください。次のようなことができます:

private MyType _someVariable = TenantType.None;
[NotNullValidator(MessageTemplate = "Some Variable can not be empty")]
public MyType SomeVariable {
    get {
        return _someVariable;
    }
    set {
        _someVariable = value;
    }
}

次に、コードで検証する場合:

Microsoft.Practices.EnterpriseLibrary.Validation.Validator myValidator = ValidationFactory.CreateValidator<MyClass>();

ValidationResults vrInfo = InternalValidator.Validate(myObject);
9
NotMe

最もきれいではないが:

public static bool ContainsNullParameters(object[] methodParams)
{
     return (from o in methodParams where o == null).Count() > 0;
}

containsNullParametersメソッドでさらにクリエイティブを取得することもできます。

public static bool ContainsNullParameters(Dictionary<string, object> methodParams, out ArgumentNullException containsNullParameters)
       {
            var nullParams = from o in methodParams
                             where o.Value == null
                             select o;

            bool paramsNull = nullParams.Count() > 0;


            if (paramsNull)
            {
                StringBuilder sb = new StringBuilder();
                foreach (var param in nullParams)
                    sb.Append(param.Key + " is null. ");

                containsNullParameters = new ArgumentNullException(sb.ToString());
            }
            else
                containsNullParameters = null;

            return paramsNull;
        }

もちろん、インターセプターまたはリフレクションを使用することもできますが、これらは簡単に追跡/使用でき、オーバーヘッドもほとんどありません

0
Jeff Grizzle