2013-01-12 8 views
5

なぜexpr1はコンパイルされますが、expr2はコンパイルされませんか?.NETの式の型は関数からの構築を許可しますが、変換はできません。

Func<object> func =() => new object(); 
Expression<Func<object>> expr1 =() => new object(); 
Expression<Func<object>> expr2 = func; //Cannot implicitly convert type 'System.Func<object>' to 'System.Linq.Expressions.Expression<System.Func<object>>' 
+1

ロットで動作し、それはあなたのニーズに合った場合は、常にこの操作を行うことができます覚えているだろうではない

Expression<Func<object>> expr2 = func; 

しかし、他の方法で回避できる理由です

: 'Func func =()=>新しいオブジェクト();式> expr2 =()=> func(); ' – JLRishe

答えて

4

A Func<T>Expression<Func<T>>は式ツリー(動作について説明ツリー状のデータ構造)であるが、デリゲート(関数へのポインタ)です。彼らは完全に異なっているので、あなたは他に1つを割り当てることはできません。

ラムダ関数をFunc<T>に直接割り当てると、コンパイラは関数のコードをコンパイルし、コンパイルされたコードへのポインタをたとえばに割り当てます。 func

一方、ラムダ関数をExpression<Func<T>>に直接割り当てると、コンパイラは式ツリー(単純に参照型のインスタンス)を構築し、そのオブジェクトへの参照を例えば次のように割り当てます。 expr1。これはコンパイラが提供する便利な機能です。コード内で手動で式ツリーを作成するよりもはるかに魅力的なオプションを提供します(これはもちろん完全に可能です)。

+0

もちろん、コンパイラは異なる(無関係な)型を見ます。コンパイラは '' func'をラムダ式であることを「調べる」ことができないと思います(おそらく私はコンパイラデザイナーではないと言えるでしょう)? – Christian

+2

@ChristianラムダにはCLR型がありません。ラムダをどこにでも "保存"することはできません。あなたは何かにそれを変換することができますが、それはもはやラムダではありません。私の答えを見てください。 – usr

0

System.Func<object>System.Linq.Expressions.Expression<System.Func<object>>は異なるタイプです。それらを暗黙的に変換することはできません。

Func<T>は代理人です。 MSDNからご覧ください。

パラメータを持たないメソッドをカプセル化し、Tパラメータで指定された型の値を として返します。

Expression<Func<T>>は発現木である。

+0

次にexpr1が正当な理由は何ですか? – miniBill

+1

@miniBill C#はラムダからいずれかの型への暗黙的な変換を可能にするためです。 – JLRishe

+1

意味があります、ありがとう:) – miniBill

3

FuncExpressionの間では変換できません。しかしラムダからどちらかに変換することができます。

ラムダは、がC#タイプシステムにのみ存在する特別なタイプです。 CLRはラムダが何であるかを知らない。 C#コンパイラだけがそれを知っていて、ラムダでできる操作は、FuncExpressionの型に変換することです。 (つまり、CLR型がまったくないため、ラムダを呼び出すことはできません)。

ここでは、「セマンティックギャップ」を観察しています。

2

簡単な言葉では、コンパイラは

  • Expression
  • 又はにコードのチャンク(ラムダ表現)に変換することができるFunc

これは、ときに直ちに起こります使用されると、コードはなくなり、非可逆的に変換されます。 しかし、FuncExpressionは完全に異なるタイプです。あなたは以下の良い説明の

Func<object> func2 = expr1.Compile(); 
関連する問題