109

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

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

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

...私がそうではないと期待するすべての議論についてnull

Nullable<>同じように、次のことが失敗するのとは反対のことがありますか?

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

6 に答える 6

70

There's nothing available at compile-time, unfortunately.

I have a bit of a hacky solution which I posted on my blog recently, which uses a new struct and conversions.

In .NET 4.0 with the Code Contracts stuff, life will be a lot nicer. It would still be quite nice to have actual language syntax and support around non-nullability, but the code contracts will help a lot.

I also have an extension method in MiscUtil called ThrowIfNull which makes it a bit simpler.

One final point - any reason for using "if (null == arg)" instead of "if (arg == null)"? I find the latter easier to read, and the problem the former solves in C doesn't apply to C#.

于 2008-11-14T20:49:25.480 に答える
32

私はこの質問に非常に遅れていることを知っていますが、C# の最新の主要なイテレーションがリリースに近づき、その後リリースされるにつれて、答えが適切になると感じています。C# 8.0 では大きな変更が行われ、C# はすべての型が null ではないと見なされるようになります。

マッツ・トーガーセンによると:

問題は、null 参照が非常に便利であることです。C# では、これらはすべての参照型の既定値です。他にデフォルト値は何ですか?他に何を代入するかを決めるまで、変数には他にどのような値がありますか? 新たに割り当てられた参照の配列を埋めるまで、他にどのような値を追加できますか?

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

したがって、Mads によって概説された解決策は次のとおりです。

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

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

  3. 面倒な null 値が必要であると積極的に判断しない限り、面倒な null 値で自分自身や消費者に負担をかけるべきではないのは当然のことです。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+ プレビューで利用できます。

于 2018-02-08T16:50:00.707 に答える
18

私はこれが非常に古い質問であることを知っていますが、これはここにありませんでした:

ReSharper/Rider を使用する場合は、Annotated Frameworkを使用できます。

編集:この回答に対してランダムに-1を取得しました。それはいいです。C#8.0 以降のプロジェクトで推奨されるアプローチではなくなりましたが、まだ有効であることに注意してください (理由を理解するには、 Greg の回答を参照してください)。

于 2013-03-07T21:48:38.383 に答える
9

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

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);
于 2008-11-14T21:23:47.003 に答える
0

最もきれいではありませんが:

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;
        }

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

于 2011-04-05T12:50:58.440 に答える
-3

この返信は少し遅れていますが、これが私がそれを解決する方法です:

public static string Default(this string x)
{
    return x ?? "";
}

この拡張メソッドを使用すると、null と空の文字列を同じものとして扱うことができます。

例えば

if (model.Day.Default() == "")
{
    //.. Do something to handle no Day ..
}

どこでもデフォルトを呼び出すことを覚えておく必要があるため、理想的ではありませんが、それは1つの解決策です。

于 2011-10-04T22:09:28.760 に答える