2011-08-10 12 views
2

質問はone by John Kと似ていますが、より具体的で、受け入れられる答えが私のニーズに合っていません。式でLambdaExpressionを初期化できません。

これは罰金コンパイル:

Expression<Func<object, object>> specificExpression = (object o) => new object(); 
Expression generalExpression = specificExpression; 

そして、この1はしません:

Expression generalExpression = (object o) => new object(); 

は、コンパイルエラーを報告しました:

Cannot convert lambda expression to type 'System.Linq.Expressions.Expression' because it is not a delegate type

Expression<Func<T1,T2>>Expressionに由来します。

ここでは、すべての種類の式を受け入れるメソッドを持つフレームワーク、つまりExpressionがあります。明示的にラムダを対応するExpression<Func<T1,T2>>にそれぞれのメソッド呼び出しで強制的にキャストするのは不愉快です。

この場合、この基本的なOOPの動作が壊れている理由はありますか?

答えて

8

コンパイラが作成しようとしている特定の式の種類を推測できないため、変換が機能しません。もしあなたがこれをしたら?

Expression generalExpression = (object o) => "foo"; 

これはExpression<Func<object, string>>である必要がありますか? Expression<Func<object, object>>またはExpression<Func<object, IComparable>>はどうですか?これらの型はすべて式ツリーの有効な最終型であり、コンパイラはあなたがしようとしていることを知っているふりをしていません。

あなたが生成する式のタイプをコンパイラに知らせるために、特定のタイプでキャストする必要があります。

Expression generalExpression = (Expression<Func<object, object>>) 
    (object o) => new object(); 

あなたはこの試みた場合は、同様のコンパイラエラーを参照してくださいになります。

Delegate generalDelegate = delegate() { }; 

Action、またはThreadStart、または他の種類の引数のない戻り値のあるデリゲートですか?

+0

この論理に従うと、 '' var''キーワードは常にコンパイル時エラーを生成します。 '' var o = "abc" ''は '' Object''である可能性がありますか?どういうわけか、型推論は '' var''で動作し、私の例ではすべての情報が実際に提供されています(引数型と戻り型は推測できます)。 –

+0

'var'は、式の右辺が評価されるどんな型でも変数を宣言するように特に定義されています。この場合、コンパイラは式の右辺が何であるかをまだ知りません! *任意のデリゲート型または*任意の*式の型にすることができます。この場合、コンパイラは "予想される型"を使って右側の処理方法を決定できますが、左側の型に 'var'や' Delegate'や 'Expression'を使うと、右側の式の型を解決するコンパイラ。 – cdhowie

+0

つまり、 'Expression >'型の変数にラムダを代入することによって、コンパイラは 'object'を取る式ツリーとしてラムダを解決するヒントを得て、オブジェクト '。しかし、 'Expression'型の変数に代入すると、コンパイラがラムダをどの型に変換する必要があるかを理解するのに十分な有用な情報が含まれていません。 – cdhowie

0

あなたは

Expression<Func<object, object>> specificExpression = (object o) => new object();

を書くときそれが実際にC#コンパイラは、私たちに提供している書き込みの容易さです。

この式は、実際にこのような何かにコンパイルされます。

Expression.Lambda<Func<object, object>> specificExpression = Expression.Lambda<Func<object,object>> (...) 

を、あなたが見ることができるように最初のexpessionがエラーで私たちを誘導し、私たちはこのことを信じてみましょうことができたとしても、Expression<Func<object,object>>はデリゲート型ではありませんその場合です。

"Expression"はデリゲート型ではないため、コンパイラーは容易に書くことができないため、デリゲートオブジェクトを直接割り当てることはできません(Expression<T>クラスの場合と同じです)。

申し訳ありませんが、あなたはイライラするようにしなければなりません。

Riana

+0

私はあなたが意味すると仮定します: '' Expression > specificExpression = Expression.Lambda >(...) '' もしそうなら、それは役に立つ情報です。しかし、まだ、 ''式generalExpression = Expression.Lambda >(...) ''はうまく動作し、それは私が望むものです... –

0

C#コンパイラは、例えば、少なくとも複雑な形に式を評価:

var x = (object o) => new object(); 

xFunc<object, object>なく、Expression<Func<object, object>>であるべきです。この場合、コンパイラは値がデリゲートであると判断し、Expressionはデリゲートを取ることができないため(Expression<Func<>>/Expression<Action>タイプのみ)、コンパイラエラーがスローされます。

また、式の形式がコンパイラによって書き直されているため、@ Rianaの答えを参照してください。

+1

実際には '' var''アプローチ暗黙的に型付けされたローカル変数にラムダ式を代入できないというコンパイルエラーが発生します。 –

+0

これは、 'Delegate x =(object o)=> new object();がエラーを起こすのと同じ理由でエラーを出すでしょう - コンパイラがデリゲート/式の型を判断するための文脈情報が不十分です作成した。 – cdhowie

関連する問題