5

expr1はコンパイルされますがexpr2はコンパイルされないのはなぜですか?

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>>'
4

4 に答える 4

4

AFunc<T>はデリゲート(関数へのポインター)であり、anExpression<Func<T>>は式ツリー(操作を記述するツリーのようなデータ構造)です。したがって、完全に異なるため、一方を他方に割り当てることはできません。

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

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

于 2013-01-12T21:01:15.797 に答える
3

FuncExpressionタイプの間で変換することはできません。ただし、ラムダからどちらかに変換できます。

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

そのため、ここで「セマンティックギャップ」を観察します。

于 2013-01-12T21:18:09.507 に答える
2

簡単に言うと、コンパイラーはコードのチャンク(ラムダ式)をに変換できます

  • Expression
  • または_Func

これは使用するとすぐに発生し、コードはなくなり、元に戻せなくなります。しかしFunc、とExpressionは完全に異なるタイプです。

だからできない

Expression<Func<object>> expr2 = func;

しかし、逆の方法でうまくいくでしょう

Func<object> func2 = expr1.Compile();
于 2013-01-12T22:35:17.297 に答える
0

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

Func<T>代理人です。から見てくださいMSDN

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

Expression<Func<T>>式ツリーです。

于 2013-01-12T21:01:58.740 に答える