2016-07-05 5 views
33

私はC#に新たなんだと言語機能を探索しながら、私は奇妙な何かに出くわした:カッコが必要な理由を式でnullableを使用するときにC#で括弧が必要なのはなぜですか?

struct Foo 
{ 
    public Foo Identity() { return this; } 

    public static void Bar(Foo? foo) 
    { 
     Foo foo1 = foo?.Identity().Value; // Does not compile 
     Foo foo2 = (foo?.Identity()).Value; // Compiles 
    } 
} 

誰も私に説明してもらえますか?

+1

の実際の結果であるFoo?です。 2番目のステートメントでは、 'Value'は' Nullable 'のプロパティを参照しています。 – xfx

+9

本当に考えているなら、null条件付き演算子を含む式の '.Value'を呼び出すことは矛盾しています(あなたはnullを期待するか、そうでないと思います)。代わりにヌル集合演算子を使用したい場合は、かっこは必要ありません。例: 'Foo foo2 = foo?.Identity()?? '; – sstan

答えて

41

括弧が必要な理由は誰でも説明できますか?

Identity()Fooを返す(Foo?ない)、したがって、何らValue性を有していないので。 fooがヌルの場合、nullはIdentityコールを介して伝播します。

あなたはそれの前後に括弧を挿入すると、表現の結果はValue性質を持ってNullable<Foo>です。

foo nullの場合、あなたが値を持たないNullable<Foo>Valueを呼び出すことになり、実行時で例外を取得することに注意してください。いくつかのスタティック・アナライザーは、発生するのを待って警告する可能性のあるヌル参照例外があることを認識します。

あなたはnullを伝播することなく、それらの等価物にそれらを展開すると、それがより明確になります。

Foo foo1; 
if(foo != null) 
{ 
    foo1 = foo.Identity().Value; // not possible - Foo has no Value property. 
} 
else 
{ 
    foo1 = null; // also not possible 
} 

Foo foo2; 
Foo? temp; 
if(foo != null) 
{ 
    temp = foo.Identity(); 
} 
else 
{ 
    temp = null; // actually a Nullable<Foo> with no value 
} 
foo2 = temp.Value; // legal, but will throw an exception at run-time if foo is null 

Identity()もし戻っFoo、なぜFoo foo3 = foo?.Identity();はコンパイルされませんか?

それと同等のもののようになります。

Foo foo3 
if(foo != null) 
{ 
    foo3 = foo.Identity(); 
} 
else 
{ 
    foo3 = null; // not possible 
} 
+0

同じ記号を使用して異なる演算子を意味する喜び。 – BoltClock

+0

あなたは私の非常に遅いコンピュータとネットワークに勝ちました:) –

+0

'Identity()'が 'Foo'を返すと、なぜ' Foo foo3 = foo?.Identity(); 'はコンパイルされませんか? – Lukas92

0

私はこのようにそれを行うには、C#のチームから良い決断だったと思います。構造体であった場合

:以下のシナリオを考えてみましょう

struct Foo 
{ 
    public int ID { set; get; } 

    public Foo Identity() { return this; } 

    public static void Bar(Foo? foo) 
    { 
     int? foo1 = foo?.Identity().ID; // compile 
     Foo foo2 = (foo?.Identity()).Value; // Compiles 
    } 
} 

あなたがNULL可能結果にアクセスするために括弧を必要としなかった場合、あなたはIDプロパティにアクセスすることはできません。下記以来コンパイルされません。

int? foo2 = (foo?.Identity()).GetValueOrDefault()?.ID 

をあなたは.Identity()で返されるタイプFooの後にあるものfoo?.Identity().を書くとき。しかし(foo?.Identity()).に何.後であることは、あなたが存在しない `Foo`、中に[値]という名前のメンバーにアクセスしようとしている最初のケースで全体の文foo?.Identity().

関連する問題