c# - 判定 - null条件演算子




2つの疑問符は、C#で何を意味するのでしょうか? (11)

このコード行に跨って:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

2つの疑問符はどういう意味ですか、何らかの三元演算子ですか? Googleで検索するのは難しいです。


注意:

私はこのスレッドと他の多くのものを全部読んだが、これは完全な答えとして見つけることができない。

それで私は「なぜ使うべきか」と「使用するタイミング」と「使用方法」を完全に理解しました。

ソース:

Windowsコミュニケーションファンデーション、Craig McMurtry著ISBN 0-672-32948-4

NULL値型

ある値が値型のインスタンスに割り当てられているかどうかを知りたい場合は、2つの一般的な状況があります。 1つは、インスタンスがデータベース内の値を表す場合です。 このような場合、インスタンスがデータベース内に実際に値が存在するかどうかを調べることができます。 この本の主題に関連するもう1つの状況は、インスタンスがリモートソースから受け取ったデータ項目を表すときです。 再度、そのデータ項目の値が受信されたかどうかをインスタンスから判断したいと思う。

.NET Framework 2.0には、値型のインスタンスにnullを割り当てたい場合や、インスタンスの値がnullかどうかをテストするための汎用型定義が組み込まれています。 その汎用型の定義はSystem.Nullableであり、これはTを値の型に置き換える可能性のあるジェネリック型の引数を制約します。 System.Nullableから構築された型のインスタンスには、nullの値を割り当てることができます。 実際、その値はデフォルトではnullです。 したがって、System.Nullableから構築された型はnull値型と呼ばれることがあります。 System.NullableにはプロパティValueがあります。この値によって、インスタンスの値がnullでない場合は、そこから構築された型のインスタンスに割り当てられた値を取得できます。 したがって、次のように書くことができます。

System.Nullable<int> myNullableInteger = null;
myNullableInteger = 1;
if (myNullableInteger != null)
{
Console.WriteLine(myNullableInteger.Value);
}

C#プログラミング言語は、System.Nullableから構築された宣言型のための省略構文を提供します。 その構文は省略できます:

System.Nullable<int> myNullableInteger;

int? myNullableInteger;

コンパイラは、このように、null値型の値を普通の値型に代入しようとしないようにします:

int? myNullableInteger = null;
int myInteger = myNullableInteger;

nullable値の型が値nullを持つ可能性があるため、実際にはこの値がnullになり、その値を通常の値型に割り当てることはできません。 コンパイラはこのコードを許可しますが、

int? myNullableInteger = null;
int myInteger = myNullableInteger.Value;

System.Nullableから構築された型にTの有効な値が割り当てられていない場合、System.Nullable.Valueプロパティにアクセスしようとする試みが無効な操作であるため、2番目のステートメントは例外をスローします場合。

結論:

null値型の値を通常の値型に割り当てる適切な方法の1つは、System.Nullable.HasValueプロパティを使用して、Tの有効な値がNULL値型に割り当てられているかどうかを確認することです。

int? myNullableInteger = null;
if (myNullableInteger.HasValue)
{
int myInteger = myNullableInteger.Value;
}

別のオプションは、この構文を使用することです:

int? myNullableInteger = null;
int myInteger = myNullableInteger ?? -1;

後者に有効な整数値が割り当てられている場合、通常の整数myIntegerにはnull可能な整数 "myNullableInteger"の値が割り当てられます。 それ以外の場合、myIntegerには-1の値が割り当てられます。


"ヌル合体演算子"( )を指し示す数多くの回答が正しく指摘されているように、その同居者にはその従兄弟をチェックしたいと思うかもしれません。 "Null-conditional Operator"( または )それと一緒に何度も使用されていますか?

ヌル条件付き演算子

メンバアクセス( )またはインデックス( )の操作を実行する前にnullをテストするために使用されます。 これらの演算子を使用すると、特にデータ構造に降下する際に、ヌルチェックを処理するコードを少なくすることができます。

例えば:

// if 'customers' or 'Order' property or 'Price' property  is null,
// dollarAmount will be 0 
// otherwise dollarAmount will be equal to 'customers.Order.Price'

int dollarAmount = customers?.Order?.Price ?? 0; 

古い方法では?? これを行うのは

int dollarAmount = customers != null 
                   && customers.Order!=null
                   && customers.Order.Price!=null 
                    ? customers.Order.Price : 0; 

これはより冗長で扱いにくいものです。


あなたがRubyをよく知っているなら、その||= C#のように見えます?? 私に。 ここにいくつかのRubyがあります:

irb(main):001:0> str1 = nil
=> nil
irb(main):002:0> str1 ||= "new value"
=> "new value"
irb(main):003:0> str2 = "old value"
=> "old value"
irb(main):004:0> str2 ||= "another new value"
=> "old value"
irb(main):005:0> str1
=> "new value"
irb(main):006:0> str2
=> "old value"

そして、C#では:

string str1 = null;
str1 = str1 ?? "new value";
string str2 = "old value";
str2 = str2 ?? "another new value";

あなたの娯楽のためだけに(あなたはC#の人たちだと知っています;-)。

私はそれがSmalltalkで始まったと思います。そこでは何年も前からありました。 そこには以下のように定義されています:

オブジェクト内:

? anArgument
    ^ self

UndefinedObject(別名nilクラス):

? anArgument
    ^ anArgument

これの評価版(?)と非評価版(??)の両方があります。
これは、ゲットメソッドで、遅延が初期化されたプライベート(インスタンス)変数のためによく見受けられます。


これは、三項演算子と同様に機能するヌル合体演算子です。

    a ?? b  => a !=null ? a : b 

もう1つの興味深い点は、 「null可能型には値を含めることができますが、それは未定義です」ということです。 したがって、ヌル可能な値の型をnull値のない値の型に代入しようとすると、コンパイル時のエラーが発生します。

int? x = null; // x is nullable value type
int z = 0; // z is non-nullable value type
z = x; // compile error will be there.

だから、それを使うには? オペレーター:

z = x ?? 1; // with ?? operator there are no issues


それはヌル合体演算子であり、3項演算子(immediate-if)とよく似ています。 参照してください 演算子 - MSDN

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

次のように展開されます。

FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();

これはさらに次のように拡張されます。

if(formsAuth != null)
    FormsAuth = formsAuth;
else
    FormsAuth = new FormsAuthenticationWrapper();

英語では、「左に何があってもヌルでない場合はそれを使用し、そうでなければ右にあるものを使用する」ことを意味します。

任意の数を順番に使用できます。 次の文は、最初のnullでないAnswer#Answer割り当てます(すべてのAnswersがnullで、 Answerがnullの場合)。

string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;

上記の展開は概念的には同等ですが、各式の結果は一度しか評価されません。 たとえば、式が副作用を伴うメソッド呼び出しである場合、これは重要です。 (これを指摘するための@Joeyへの献金)


みなさん、ありがとう、ここで私がMSDNサイトで見つけた最も簡単な説明です:

// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;

合体オペレータ

それは

FormsAuth = formsAUth == null ? new FormsAuthenticationWrapper() : formsAuth

誰もまだ魔法の言葉を言っていないからです。それはヌル合体オペレータです。 これは、 C#3.0言語仕様のセクション7.12で定義されています。

非常に便利です。特に、式で複数回使用されているときに動作するためです。 次の形式の式

a ?? b ?? c ?? d

それがNULLでない場合は式aの結果を返し、それ以外の場合はb試み、そうでない場合はc試行し、そうでない場合はd試行します。 それはあらゆる点で短絡する。

また、 dの型がnullableでない場合、式全体の型もnullableではありません。


FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();

しかし、それについてのクールなことは、他の人が言ったように、あなたはそれらをチェーンすることができるということです。 触れられていない薄いものは、実際にそれを使って例外を投げることができるということです。

A = A ?? B ?? throw new Exception("A and B are both NULL");




null-coalescing-operator