2016-05-17 9 views
22

私はVS 2010から2015にアップグレードしました。私は新しいnull-conditional operatorが好きです。これはヌル伝播としても知られています。これは、例えば、あなたのコードを簡素化することができます:ヌル条件演算子はboolではなくboolに評価されますか?期待通りに

string firstCustomerName = customers?[0].Name; // null if customers or the first customer is null 

別の1:

Enumerable.Countが有効数と任意の nulls前に区別するために intを返す場合でも Nullable<int>を返し
int? count = customers?[0]?.Orders?.Count(); // null if customers, the first customer, or Orders is null 

。それは非常に直感的で非常に便利です。

しかし、なぜ期待通り(それはfalseを返します)このコンパイル作業を行います。

string text = null; 
bool contains = text?.IndexOf("Foo", StringComparison.CurrentCultureIgnoreCase) >= 0; 

これは、コンパイル(それはない)bool?を返すかべきではないのいずれか。あなたが実際に持っている何

+5

おっとを、私はあなたができる、私はそれを自分自身を持っていると思いますそれを書き直してください: 'int? indexof =テキスト?.IndexOf( "Foo"、StringComparison.CurrentCultureIgnoreCase); bool contains = indexof> = 0; ' –

+4

私は'?> = '演算子に投票します。:) –

+0

@DStanley:他の[オペレータカテゴリ](https://msdn.microsoft.com/en-us/library/aa691323(v = vs.71).aspx)を含むものもあります。良いよりも害を及ぼすでしょう。 –

答えて

28

string text = null; 
int? index = text?.IndexOf("Foo", StringComparison.CurrentCultureIgnoreCase); 
bool contains = index >= 0; 

int? >= intは完全に合法です。

the documentation for the operatorの状態"条件メンバーアクセスチェーンとインデックス操作の1つの操作でnullが返された場合、残りのチェーンの実行は停止します。 "つまり、.?は、「値を作成する」前に同じ優先順位以上のものだけを評価します。

the order of operator precedenceを見ると、 "Relational and Type-Testing Operators"のほうがリストのほうがずっと低いので、>=が適用される前に値が作成されることがわかります。


UPDATE:それはコメントで育ったので、ここではNULL可能値を扱うとき>=と他の事業者がどのように動作するかのC#5仕様セクションがあります。私はC#6

7.3.7つり事業者

つりオペレータ許可が事前に定義し、null非許容値型で動作するユーザー定義演算子もNULL可能で使用するためのドキュメントを見つけることができませんでしたこれらのタイプのフォーム。持ち上げ演算子は は、以下に記載されるように、一定の要件を満たし 定義済みおよびユーザ定義演算子から構成されている:

  • 単項演算子
    + ++ - -- ! ~

    についてオペレータの持ち上げ形が存在する場合オペランドと結果の型は共にnull値ではない値の型です。持ち上げられたフォームは です。修飾子はオペランドに、結果は となります。持ち上げられた演算子は、オペランドが であればヌル値を生成します。それ以外の場合、持ち上げられたオペレータはオペランドをアンラップし、基礎となるオペレータ を適用し、結果をラップします。バイナリ演算子
    について

  • + - */% & |^<< >>

    オペレータの持ち上げ形態は、オペランドと結果種類 は、すべての非null許容値型である場合に存在します。持ち上げられたフォームは、 によって追加されますか?修飾子を各オペランドと結果の型に追加します。持ち上げられた 演算子は、一方または両方のオペランドがNULLの場合にNULL値を生成します( の例外は&で、bool?型の演算子は§7.11.3の となります)。それ以外の場合、持ち上げられた演算子はオペランドをアンラップし、 は基本となる演算子を適用し、結果をラップします。オペランドタイプが両方 非null許容値型である場合、結果タイプはブールである場合にオペレータの解除フォームが存在
    == !=

    等価演算子について

  • 。持ち上げられた フォームは、単一の?修飾子は各オペランド タイプに対応します。持ち上げられた演算子は、2つのヌル値が等しいとみなし、ヌル値は0以外の値と等しくないヌル値を返します。両方のオペランドがヌルでない場合、 持ち上げられたオペレータはオペランドをアンラップし、下位の オペレータを適用してブール結果を生成します。オペランドタイプがnull非許容値型の両方である場合、結果の型はブールである場合にオペレータの解除フォームが存在
    < > <= >=

    関係演算子について

  • 。持ち上げられた フォームは、単一の?修飾子は各オペランド タイプに対応します。持ち上げられた演算子は、オペランドの1つまたは両方がヌルの場合、値falseを生成します。それ以外の場合、持ち上げられたオペレータはオペランド をアンラップし、基礎となる演算子を適用してブール結果を生成します。

+0

C#の知識があまりない私たちの場合、 'Nullable'が実際にnullのときの演算子'> = 'の動作はどうですか? – njzk2

+0

@ njzk2単純な言い方をすれば、 '> ='のいずれかの側または両側がnullの場合、常にfalseを返します。完全な仕様については、私のアップデートを参照してください。 –

+0

ありがとう@ScottChamberlain – njzk2

3

あなたはこのコードを使用し、xの上に置くと、あなたはxint?であることを参照してください。

var x = text?.IndexOf("Foo", StringComparison.CurrentCultureIgnoreCase); 
bool contains = x >= 0; 

ので、タイピングが正しいです。

次に、x >= 0を見てください:int? >= intです。外見上、nullable構造体とnullable構造体の間に演算子があります。それがなぜ機能するのですか。

ILを見ると、実際にはHasValueGetValueOrDefault()が呼び出されます。私はこれを行うオペレータがあると思いますが、それはCLRまたはコンパイラにする必要がありますので、私は、リファレンスソースでそれを見つけることができませんでした:

instance !0 valuetype [mscorlib]System.Nullable`1<int32>::GetValueOrDefault() 

... 
instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue() 
+1

真ですが、null条件付き演算子に 'bool? 'を返す'> ='演算子が含まれている可能性があります。しかし、これは、[_ _ "_(https://msdn.microsoft.com/en-us/library/dn986595.aspx)の中で優先順位の低い他の操作が続行されていると思われます。 –

関連する問題