170

C# でnull 合体演算子を使用する標準的な方法は、既定値を設定することです。

string nobody = null;
string somebody = "Bob Saget";
string anybody = "";

anybody = nobody   ?? "Mr. T"; // Returns Mr. T
anybody = somebody ?? "Mr. T"; // Returns "Bob Saget"

しかし、他に何??に使用できますか?以下よりも簡潔で読みやすいことを除けば、三項演算子ほど有用ではないようです。

nobody = null;
anybody = nobody == null ? "Bob Saget" : nobody; // Returns Bob Saget

したがって、null合体演算子について知っている人はほとんどいないことを考えると...

  • 他に使っ??たことありますか?

  • ??必要ですか、または三項演算子を使用する必要がありますか (ほとんどの人が使い慣れています)

4

16 に答える 16

224

まず第一に、標準の三項演算子よりも連鎖する方がはるかに簡単です。

string anybody = parm1 ?? localDefault ?? globalDefault;

対。

string anyboby = (parm1 != null) ? parm1
               : ((localDefault != null) ? localDefault
               : globalDefault);

null の可能性のあるオブジェクトが変数でない場合にもうまく機能します。

string anybody = Parameters["Name"]
              ?? Settings["Name"]
              ?? GlobalSetting["Name"];

対。

string anybody = (Parameters["Name"] != null ? Parameters["Name"]
                 : (Settings["Name"] != null) ? Settings["Name"]
                 :  GlobalSetting["Name"];
于 2008-11-10T18:25:22.957 に答える
178

私はそれを遅延ロードのワンライナーとして使用しました:

public MyClass LazyProp
{
    get { return lazyField ?? (lazyField = new MyClass()); }
}

読める?自分で決めてください。

于 2008-11-10T18:25:55.573 に答える
53

私はそれが2つの「少し変わった」方法で役立つことを発見しました:

  • outルーチンを記述するときにパラメーターを持つ代わりにTryParse(つまり、解析が失敗した場合は null 値を返す)
  • 比較のための「わからない」表現として

後者にはもう少し情報が必要です。通常、複数の要素を使用して比較を作成する場合、比較の最初の部分 (年齢など) で決定的な答えが得られるかどうかを確認し、最初の部分が役に立たなかった場合にのみ、次の部分 (名前など) を確認する必要があります。null 合体演算子を使用すると、非常に単純な比較 (順序付けまたは等価) を記述できることを意味します。たとえば、MiscUtilでいくつかのヘルパー クラスを使用します。

public int Compare(Person p1, Person p2)
{
    return PartialComparer.Compare(p1.Age, p2.Age)
        ?? PartialComparer.Compare(p1.Name, p2.Name)
        ?? PartialComparer.Compare(p1.Salary, p2.Salary)
        ?? 0;
}

確かに、MiscUtil に ProjectionComparer があり、いくつかの拡張機能があり、この種の作業がさらに簡単になりますが、それでもうまくいきます。

Equals の実装開始時の参照の等価性 (または null 性) のチェックについても、同じことができます。

于 2008-11-10T19:30:56.957 に答える
34

もう 1 つの利点は、三項演算子が double 評価または一時変数を必要とすることです。

たとえば、次のように考えてください。

string result = MyMethod() ?? "default value";

三項演算子を使用すると、次のいずれかが残ります。

string result = (MyMethod () != null ? MyMethod () : "default value");

MyMethod を 2 回呼び出す、または:

string methodResult = MyMethod ();
string result = (methodResult != null ? methodResult : "default value");

いずれにせよ、null 合体演算子はよりクリーンで、おそらくより効率的です。

于 2008-12-19T21:30:48.813 に答える
15

オペレーターにとって私が見つけた最大の利点??は、null 許容値型を null 非許容型に簡単に変換できることです。

int? test = null;
var result = test ?? 0; // 'result' is int, not int?

私はこれを LINQ クエリでよく使用します。

Dictionary<int, int?> PurchaseQuantities;
// PurchaseQuantities populated via ASP .NET MVC form.
var totalPurchased = PurchaseQuantities.Sum(kvp => kvp.Value ?? 0);
// totalPurchased is int, not int?
于 2012-11-27T22:25:08.233 に答える
9

??IDataErrorInfo の実装で使用しました。

public string Error
{
    get
    {
        return this["Name"] ?? this["Address"] ?? this["Phone"];
    }
}

public string this[string columnName]
{
    get { ... }
}

個々のプロパティが「エラー」状態にある場合はそのエラーが発生し、それ以外の場合は null になります。それは本当にうまくいきます。

于 2008-11-11T09:56:36.490 に答える
7

null 合体演算子を使用して、オプションのパラメーターが設定されていない場合を処理するのを少しきれいにすることができます。

public void Method(Arg arg = null)
{
    arg = arg ?? Arg.Default;
    ...
于 2013-07-01T07:45:01.867 に答える
6

null 合体演算子を使用して、特定のプロパティを遅延ロードするのが好きです。

私の要点を説明するための非常に単純な(そして不自然な)例:

public class StackOverflow
{
    private IEnumerable<string> _definitions;
    public IEnumerable<string> Definitions
    {
        get
        {
            return _definitions ?? (
                _definitions = new List<string>
                {
                    "definition 1",
                    "definition 2",
                    "definition 3"
                }
            );
        }
    } 
}
于 2014-06-19T14:51:43.467 に答える
6

私が最近頻繁に行っていることの 1 つは、 へのバックアップに null 合体を使用することですas。例えば:

object boxed = 4;
int i = (boxed as int?) ?? 99;

Console.WriteLine(i); // Prints 4

?.また、それぞれが失敗する可能性のある長いチェーンをバックアップするのにも役立ちます

int result = MyObj?.Prop?.Foo?.Val ?? 4;
string other = (MyObj?.Prop?.Foo?.Name as string)?.ToLower() ?? "not there";
于 2016-06-29T14:09:47.800 に答える
5

は ??必要な場合、または三項演算子を使用する必要があります (ほとんどの人が慣れ親しんでいます)。

実際、私の経験では、三項演算子 (または、より正確には条件演算子)に精通している人はほとんどいないということです。?:同じ意味で「三項」とは、||2 項または+単項または 2 項のいずれかです。ただし、たまたま多くの言語で唯一の三項演算子)、少なくともその限られたサンプルでは、​​ステートメントはすぐに失敗します。

また、前述のように、null 合体演算子が非常に役立つ主な状況が 1 つあります。それは、評価される式に何らかの副作用がある場合です。その場合、(a) 一時変数を導入するか、(b) アプリケーションの実際のロジックを変更しない限り、条件演算子を使用することはできません。(b) はどのような状況でも明らかに適切ではありません。個人的な好みではありますが、たとえ寿命が短いとしても、多くの無関係な変数で宣言スコープを混乱させるのは好きではないので、(a) もその中では役に立ちません。特定のシナリオ。

もちろん、結果に対して複数のチェックを行う必要がある場合は、条件演算子または一連のifブロックがおそらくそのツールになります。しかし、「これがnullの場合はそれを使用し、そうでない場合はそれを使用する」という単純な場合、null合体演算子??は完璧です。

于 2011-02-15T13:12:03.567 に答える
4

唯一の問題は、null 合体演算子が空の文字列を検出しないことです。


いえ

string result1 = string.empty ?? "dead code!";

string result2 = null ?? "coalesced!";

出力

result1 = ""

result2 = coalesced!

私は現在、??のオーバーライドを検討しています。オペレーターがこれを回避します。これをフレームワークに組み込むと便利です。

于 2009-03-10T16:01:25.633 に答える
3

は ??必要な場合、または三項演算子を使用する必要があります (ほとんどの人が慣れ親しんでいます)。

意図を最もよく表すものを使用する必要があります。ヌル合体演算子があるので、それを使っください

一方で、専門的なので、それ以外の用途はないと思います。||他の言語がそうであるように、演算子の適切なオーバーロードを好みました。これは、言語設計においてより節約になります。でもまあ…</p>

于 2008-11-10T18:24:38.340 に答える
3

涼しい!私は、null 合体演算子について知らなかった人だと思ってください。

三項演算子よりも読みやすいと思います。

どこで使用する可能性があるかについて最初に思いつくのは、すべての既定のパラメーターを 1 つの場所に保持することです。

public void someMethod(object parm2, ArrayList parm3)
{
  someMethod(null, parm2, parm3);
}

public void someMethod(string parm1, ArrayList parm3)
{
  someMethod(parm1, null, parm3);
}

public void someMethod(string parm1, object parm2)
{
  someMethod(parm1, parm2, null);
}

public void someMethod(string parm1)
{
  someMethod(parm1, null, null);
}

public void someMethod(object parm2)
{
  someMethod(null, parm2, null);
}

public void someMethod(ArrayList parm3)
{
  someMethod(null, null, parm3);
}

public void someMethod(string parm1, object parm2, ArrayList parm3)
{
  // Set your default parameters here rather than scattered 
  // through the above function overloads
  parm1 = parm1 ?? "Default User Name";
  parm2 = parm2 ?? GetCurrentUserObj();
  parm3 = parm3 ?? DefaultCustomerList;

  // Do the rest of the stuff here
}
于 2008-11-10T18:31:37.607 に答える
2

これは少し奇妙な使用例ですが、IDisposableオブジェクトが引数として渡される可能性がある (したがって、親によって破棄される) メソッドがありましたが、null になる可能性もあります (そのため、ローカルで作成して破棄する必要があります)。方法)

それを使用するには、コードは次のようになります

Channel channel;
Authentication authentication;

if (entities == null)
{
    using (entities = Entities.GetEntities())
    {
        channel = entities.GetChannelById(googleShoppingChannelCredential.ChannelId);
        [...]
    }
}
else
{
    channel = entities.GetChannelById(googleShoppingChannelCredential.ChannelId);
    [...]
}

しかし、null 合体を使用すると、よりきれいになります。

using (entities ?? Entities.GetEntities())
{
    channel = entities.GetChannelById(googleShoppingChannelCredential.ChannelId);
    [...]
}
于 2016-12-19T18:23:02.990 に答える