web-dev-qa-db-ja.com

C#では、2つの疑問符が一緒に何かを意味しますか?

このコード行を渡って走った:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

2つの疑問符はどういう意味ですか、それはある種の3項演算子ですか? Googleで調べるのは難しいです。

1448
Edward Tanguay

これはnull合体演算子であり、3項(即値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に割り当てます(すべてのAnswersがnullの場合、Answerはnull)。

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

また、上記の展開は概念的には等価ですが、各式の結果は1回しか評価されません。たとえば式が副作用のあるメソッド呼び出しである場合、これは重要です。 (これを指摘してくれた@Joeyの功績による。)

1940
lc.

まだ誰も魔法の言葉を言っていないからといって、それは null合体演算子 です。これは C#3.0言語仕様のセクション7.12で定義されています

特に式の中で複数回使用されている場合の動作方法が非常に便利です。次の形式の式

a ?? b ?? c ?? d

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

また、dの型がNULL不可の場合、式全体の型もNULL不可です。

261
Jon Skeet

それはnull合体演算子です。

http://msdn.Microsoft.com/ja-jp/library/ms173224.aspx

はい、名前が分からない限り、検索することはほぼ不可能です。 :-)

編集:そして、これは別の質問からクールな機能です。あなたはそれらを連鎖することができます。

C#の隠れた機能

67
Iain Holder

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

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

??は、値がnullの場合にnull許容型の値を提供するためにあります。そのため、formsAuthがnullの場合、新しいFormsAuthenticationWrapper()が返されます。

20
RedFilter

enter image description here

2つの疑問符(??)は、その結合演算子であることを示しています。

結合演算子は、チェーンから最初のNON-NULL値を返します。 this youtube video を見ることができます。

しかし、ビデオの内容にさらに追加させてください。

合体の英語の意味がわかると、「一緒に統合する」と表示されます。以下の例は、4つの文字列を連結する単純な合体コードです。

str1nullの場合、str2を試行し、str2nullの場合、文字列を見つけるまでstr3を試行します。 null以外の値。

string final = str1 ?? str2 ?? str3 ?? str4;

簡単に言うと、合体演算子はチェーンから最初のNON-NULL値を返します。

18

あなたが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";
12
Sarah Vessels

これについて危険なことは何もありません。実際、それは美しいです。それが望ましい場合は、デフォルト値を追加できます。次に例を示します。

int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;

__コード__
11
dqninh

それは三項演算子にとっては手短です。

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

あるいは、三項をしない人のために:

if (formsAuth != null)
{
  FormsAuth = formsAuth;
}
else
{
  FormsAuth = new FormsAuthenticationWrapper();
}
11
Benjamin Autin

合体演算子

それはと同等です

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

多くの答えで正しく指摘されているように、それは "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; 

これはより冗長で面倒です。

10
brakeroo

あなたの娯楽のためだけに(あなたがすべてC#人であることを知っている;-)。

私はそれがSmalltalkから始まったと思います、そこでそれは長年の間ずっとありました。それは次のように定義されています。

オブジェクト内:

? anArgument
    ^ self

undefinedObject(別名nilのクラス):

? anArgument
    ^ anArgument

これには評価版(?)と非評価版(??)があります。
それは、遅延初期化されたプライベート(インスタンス)変数のためのgetter-methodsにしばしば見られます。そして、それは本当に必要とされるまでゼロのままにされます。

10
blabla999

ここで合体を使って値を取得する例のいくつかは非効率的です。

あなたが本当に欲しいのは:

return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();

または

return _formsAuthWrapper ?? (_formsAuthWrapper = new FormsAuthenticationWrapper());

これにより、オブジェクトが毎回再作成されるのを防ぎます。プライベート変数がnullのままでリクエストごとに新しいオブジェクトが作成されるのではなく、新しいオブジェクトが作成された場合にプライベート変数が割り当てられることを保証します。

9

注意:

私はこのスレッド全体と他の多くを読みましたが、私はこれほど完全な答えを見つけることができません。

それによって私は「なぜ使うのか、いつ使うのか、そしてどのように使うのか」を完全に理解しました。

出典:

Windows通信基盤が解き放たクレイグ・マクマリー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;

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

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

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

結論:

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

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

もう1つの選択肢は、この構文を使用することです。

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

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

7
Wiqi
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

と同等です

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

しかし、それについての素晴らしいことは、他の人が言ったように、それらを連鎖させることができるということです。触れられていない薄いのは、あなたが実際にそれを使って例外を投げることができるということです。

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

??演算子は、null合体演算子と呼ばれます。オペランドがNULLでない場合は、左側のオペランドを返します。それ以外の場合は、右側のオペランドを返します。

int? variable1 = null;
int variable2  = variable1 ?? 100;

variable2がNULLでない場合は、variable1variable1の値に設定します。それ以外の場合、variable1 == nullの場合、variable2を100に設定します。

0
Md.Jubayer

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

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

"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
0
Ashish Mishra