2011-12-14 5 views
3

を割り当てるには三項演算子を使用することはできません私は、次のコードを入力:は、LINQの式

Expression<Func<ContentItem, bool>> expression = 
       fileTypeGroupID.HasValue ? n => n.Document.MimeType.FileTypeGroupID == fileTypeGroupID.Value : n => true; 

Visual Studioは、それがnの種類を推測することはできませんと言っています。

コードは私にとってうまく思えます - Expression変数に2つのExpressionリテラルのうちの1つを割り当てるために3進演算子を使用しています。

Visual Studioは、3進演算子の内部でnのタイプを推測するだけのスマートではありませんか、何か間違いを犯しましたか?

答えて

12

この質問はほぼ毎日何らかの形で尋ねられます。外部から内側から

条件演算子型解析進み、内部から外部ない。条件付き演算子は、結果が代入されるタイプがの場合はを認識しません。次にの場合は、これらのタイプの結果と代替を強制します。。それは反対です。それは結果と代替のタイプを作り出し、その2つのタイプのより一般的なものをとり、一般的なタイプが割り当てられるかもしれないことを検証する。

結果と代替は、ラムダのタイプが何であるべきかに関する情報を含んでおらず、したがって、条件のタイプは推論できません。したがって、割り当てが正しいことを確認することはできません。

なぜその言語がそのように設計されたのかを検討することになります。あなたはオーバーロードがあるとします。

void M(Func<string, int> f) {} 
void M(Func<double, double> f) {} 

、コールを

M(b ? n=>n.Foo() : n => n.Bar()); 

は、オーバーロードの解決は、Mの過負荷が種類が外側から内側へと推測される世界で選ばれた決定方法について説明します。

M(b1 ? (b2 ? n=>n.Foo() : n => n.Bar()) : (b3 ? n=>n.Blah() : n=>n.Abc())); 

それを困難にされていません行き方:

は今、この1つは考えますか?今、Foo、Bar、Blah、Abc自身がfuncを取ったメソッドであり、lambdaを含む条件演算子で引数を取ったとします。

タイプ推論プロセスを非常に複雑にすることは、それほど大きなメリットはありませんが、条件付き演算子には大きな利点はありません。

あなたのケースで行うべきことは、特定のタイプの結果と代替のいずれかまたは両方をキャストすることです。

+0

なぜ 'n'に型('(ContentItem n)=> ... ')を与えた方が良いのですか? – Gabe

+0

これまでの詳細な対応に感謝します。 – David

+0

'(Expression >)(n => true)'という方法で各ラムダを明示的にキャストすると、問題は解決しましたが、コードはリファクタリングを必要とするほど醜いです! – David

1
fileTypeGroupID.HasValue ? (ContentItem n) => n.Document.MimeType.FileTypeGroupID == fileTypeGroupID.Value 
         : (ContentItem n) => true; 

条件演算子は、三項演算子の例を示します(および多くのプログラミング言語でのみ三項演算子である)? :の正しい名前です。

+2

C#で他の三項演算子であるため。 .. –

+0

C#(およびC、C++、および他の多くの言語)では* 3 * 3項演算子なので、それを "3進演算子"と呼ぶのが妥当です。ほとんどの人は、あなたが意味することを知っているでしょう。 –

+1

@ジョン、@エリック:人々は 'を知っていますが? : '三項演算子として、その用語を使っている人が正しい名前を指摘する価値があると思うということを知っている。それは私にバグがあるので、それが理由です! :) –

2

これは、コンパイラが型を推論できなかった理由のあなたの質問に答えていませんが、周りの簡単な仕事は、あなたの表現をこのように書くことになります:

Expression<Func<ContentItem, bool>> expression = 
    n => !fileTypeGroupID.HasValue || n.Document.MimeType.FileTypeGroupID == fileTypeGroupID.Value; 
+0

あなたが言っているように、尋ねられたように質問に答えるが、これは非常にエレガントな実用的な解決策である。ありがとうございました。 – David