次のコード行を実行しました。
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
2つの疑問符はどういう意味ですか、それは一種の三項演算子ですか?グーグルで調べるのは難しい。
次のコード行を実行しました。
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
2つの疑問符はどういう意味ですか、それは一種の三項演算子ですか?グーグルで調べるのは難しい。
回答:
これはnullの合体演算子であり、三項(即時IF)演算子とよく似ています。も参照してください?オペレーター-MSDN。
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
展開する:
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
これはさらに次のように拡張されます。
if(formsAuth != null)
FormsAuth = formsAuth;
else
FormsAuth = new FormsAuthenticationWrapper();
英語では、「左側にあるものがnullでない場合はそれを使用し、そうでない場合は右側にあるものを使用する」という意味です。
これらはいくつでも順番に使用できることに注意してください。次のステートメントは、最初の非null Answer#
を割り当てますAnswer
(すべての回答がnullの場合、Answer
はnullです)。
string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;
また、上記の展開は概念的には同等ですが、各式の結果は1回しか評価されませんが、言及する価値もあります。これは、たとえば式が副作用のあるメソッド呼び出しである場合に重要です。(これを指摘してくれた@Joeyへのクレジット)
??
は関連付けられたままなので、a ?? b ?? c ?? d
と同等((a ?? b) ?? c ) ?? d
です。「代入演算子と3項演算子(?:)は右結合です。他のすべての2項演算子は左結合です。」出典:msdn.microsoft.com/en-us/library/ms173145.aspx
まだ誰も魔法の言葉を言っていないからといって、それはnullの合体演算子です。これは、C#3.0言語仕様のセクション7.12で定義されています。
特に式の中で複数回使用された場合の動作方法のため、非常に便利です。フォームの式:
a ?? b ?? c ?? d
式がa
nullでない場合は式の結果が返されます。それ以外の場合はb
、それ以外の場合はc
、それ以外の場合はを試してくださいd
。あらゆる点で短絡します。
また、の型がd
null可能でない場合、式全体の型もnull可能ではありません。
これは、ヌルの合体演算子です。
http://msdn.microsoft.com/en-us/library/ms173224.aspx
はい、それが何と呼ばれるかを知らない限り、検索するのはほとんど不可能です!:-)
編集:そして、これは別の質問からのクールな機能です。あなたはそれらを連鎖させることができます。
みんなありがとう、MSDNサイトで見つけた最も簡潔な説明は次のとおりです。
// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;
-1
はありません(null可能ではない単なるint
です)。
x
型であるint?
が、y
タイプのものでありint
、あなたが書くことができますint y = (int)(x ?? -1)
。そうでない場合は解析さx
れ、int
そうでない場合はnull
代入さ-1
れます。y
x
null
2つの疑問符(??)は、その合体演算子であることを示します。
結合演算子は、チェーンから最初のNON-NULL値を返します。全体を実際に示すこのYouTubeビデオを見ることができます。
しかし、動画の内容にさらに追加してみましょう。
合体の英語の意味を見ると、「一緒に統合する」と書かれています。以下の例は、4つの文字列をチェーン化する単純な結合コードです。
つまり、そうである場合str1
はnull
試行されstr2
、そうでない場合str2
は、null以外の値を持つ文字列が見つかるまでnull
試行さstr3
れます。
string final = str1 ?? str2 ?? str3 ?? str4;
簡単に言うと、結合演算子はチェーンから最初のNON-NULL値を返します。
三項演算子の省略形です。
FormsAuth = (formsAuth != null) ? formsAuth : new FormsAuthenticationWrapper();
または、3項を行わない人のために:
if (formsAuth != null)
{
FormsAuth = formsAuth;
}
else
{
FormsAuth = new FormsAuthenticationWrapper();
}
!= null
)と2番目のテストformsAuth
(の後)の両方を?
変更できます。null合体形式では、どちらも指定した値を暗黙的に取得します。
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";
x ||= y
以下のようなものにdesugars x = x || y
ので、??
実際には無地に似ている||
Rubyで。
??
だけを気にnull
、一方||
Rubyで、オペレータは、ほとんどの言語のように、より程度であるnull
、false
またはの値をブール考えることができるものfalse
(例えば、いくつかの言語で、""
)。これは良いことでも悪いことでもありません、ただの違いです。
これについては何も危険ではありません。実は綺麗です。必要に応じて、デフォルト値を追加できます。次に例を示します。
コード
int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;
int? x1 = null;
その権利です
x1
- x4
null許容型である必要があります。つまり、「結果は0
、x4
取り得ない可能性のある値である場合」と言っても意味がありません(null
)。ここでの「null許容型」には、null許容値型と参照型の両方が含まれます。1つ以上のチェーンされた変数(最後のものを除く)がNULL可能でない場合、これはコンパイル時エラーです。
"null合体演算子"(??)である多数の回答で正しく指摘されているように、その演算子である "Null条件演算子(?。または?[)何度も使用されますか?
メンバーアクセス(?。)またはインデックス(?[)操作を実行する前にnullをテストするために使用されます。これらの演算子を使用すると、特にデータ構造に降りる場合などに、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;
より冗長で扱いにくいです。
あなたの娯楽のためだけに(あなたがすべてC#の人であることを知っている;-)。
それは、Smalltalkが起源であると私は思います。そこでは次のように定義されています。
オブジェクト内:
? anArgument
^ self
UndefinedObject(別名nilのクラス):
? anArgument
^ anArgument
これには、評価版(?)と非評価版(??)の両方があります。
これは、遅延初期化されたプライベート(インスタンス)変数のゲッターメソッドでよく見られ、本当に必要になるまでnilのままです。
結合を使用して値を取得するここでのいくつかの例は非効率的です。
あなたが本当に欲しいのは:
return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();
または
return _formsAuthWrapper ?? (_formsAuthWrapper = new FormsAuthenticationWrapper());
これにより、オブジェクトが毎回再作成されるのを防ぎます。プライベート変数がnullのままで、リクエストごとに新しいオブジェクトが作成される代わりに、新しいオブジェクトが作成された場合にプライベート変数が割り当てられます。
??
ショートカットが評価しますか?new FormsAuthenticationWrapper();
がnilの場合にのみ 評価され_formsAuthWrapper
ます。
このスレッド全体と他の多くのスレッドを読みましたが、これほど完全な答えは見つかりません。
「なぜ??を使う理由と??と使う方法??」を完全に理解した。
Windowsコミュニケーションの基盤が解き放たれるCraig McMurtry著ISBN 0-672-32948-4
値が値型のインスタンスに割り当てられているかどうかを知りたい状況は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の値が割り当てられます。
これは、3項演算子と同様に機能するnullの合体演算子です。
a ?? b => a !=null ? a : b
これに関するもう1つの興味深い点は、 「null許容型には値が含まれる場合と、未定義の場合があります」です。したがって、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
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
に相当
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
しかし、他の人が言ったように、それを連鎖させることができるというのが素晴らしいところです。触れられていないのは、実際にそれを使用して例外をスローできることです。
A = A ?? B ?? throw new Exception("A and B are both NULL");
この??
演算子は、ヌル結合演算子と呼ばれます。オペランドがnullでない場合は、左側のオペランドを返します。それ以外の場合は、右側のオペランドを返します。
int? variable1 = null;
int variable2 = variable1 ?? 100;
variable2
の値に設定されます(がnullでないvariable1
場合variable1
)。それ以外の場合はvariable1 == null
、variable2
100 に設定します。