Expression<>
の中にデリゲートをラップすることとは違いますか?Expressionクラスの目的は何ですか?
私は012QがLinQと多く使われているのを見ていますが、これまでのところ、これの違いを説明しているデリゲートを使用した記事は見つかりませんでした。
など。
Expression<Func<int, bool>> Is42 = (value) => value == 42;
Expression<>
の中にデリゲートをラップすることとは違いますか?Expressionクラスの目的は何ですか?
私は012QがLinQと多く使われているのを見ていますが、これまでのところ、これの違いを説明しているデリゲートを使用した記事は見つかりませんでした。
など。
Expression<Func<int, bool>> Is42 = (value) => value == 42;
ラムダをデリゲートとして格納すると、何らかのアクションを行うデリゲートの特定のインスタンスが格納されます。それは変更することはできません、あなたはそれを呼び出すだけです。デリゲートを取得したら、それが何をしているのか、それ以外のものを調べるオプションは限られています。
ラムダを式として格納すると、デリゲートを表す式ツリーが格納されます。パラメータを変更したり、ボディを変更したり、根本的に異なる何かをさせるなど、他の操作を行うように操作することができます。デリゲートにコンパイルすることもできますので、必要に応じて呼び出すことができます。表現を簡単に調べて、そのパラメータが何であるか、それが何であり、どのようにしているかを見ることができます。これは、クエリプロバイダが式を理解し、別の言語に翻訳するために使用できます(対応する式ツリーのSQLクエリを作成するなど)。
表現を使用してデリゲートを動的に作成することも、コードを出力するよりもずっと簡単です。あなたのコードは、コンパイラがコードを低レベルにするのではなくコードを見る方法と非常に似ていると考えることができます。
表現では、単純な匿名デリゲート以上のことができます。実際にフリーではありませんが、コンパイルされた式を通常のメソッドや匿名のデリゲートと比較して実行すると、パフォーマンスが低下します。ただし、式を使用することによるその他の利点が重要な場合があるため、それは問題ではない可能性があります。
Func<>
Func<int, bool> Is42 = (value) => value == 42;
対はちょうどデリゲート型です。式は、任意に、実行時にデリゲートにコンパイルされるoperationsという完全なツリーのランタイム表現です。この木はLinq-to-SQLのようなExpressionパーサによって解析され、SQL文を生成したり他の巧妙なことを行います。式の型にラムダを割り当てると、コンパイラはこの式ツリーと通常のILコードを生成します。 More on expression trees。
表現ツリーノードを表すクラスが派生する基底クラスを提供します。
System.Linq.Expressions.BinaryExpression
System.Linq.Expressions.BlockExpression
System.Linq.Expressions.ConditionalExpression
System.Linq.Expressions.ConstantExpression
System.Linq.Expressions.DebugInfoExpression
System.Linq.Expressions.DefaultExpression
System.Linq.Expressions.DynamicExpression
System.Linq.Expressions.GotoExpression
System.Linq.Expressions.IndexExpression
System.Linq.Expressions.InvocationExpression
System.Linq.Expressions.LabelExpression
System.Linq.Expressions.LambdaExpression
System.Linq.Expressions.ListInitExpression
System.Linq.Expressions.LoopExpression
System.Linq.Expressions.MemberExpression
System.Linq.Expressions.MemberInitExpression
System.Linq.Expressions.MethodCallExpression
System.Linq.Expressions.NewArrayExpression
System.Linq.Expressions.NewExpression
System.Linq.Expressions.ParameterExpression
System.Linq.Expressions.RuntimeVariablesExpression
System.Linq.Expressions.SwitchExpression
System.Linq.Expressions.TryExpression
System.Linq.Expressions.TypeBinaryExpression
System.Linq.Expressions.UnaryExpression
http://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.aspx
式ツリーを分析し、例えばSQLクエリに変換することができますLINQの式を表します。
Expression Treesコード内の式内のコードを検査することができます。
たとえば、この式を渡した場合、o => o.Name
は、Name
プロパティが式の中でアクセスされていることをコードが知ることができます。
あなたがそれらの2式をコンパイルした場合、他の回答を示しており、コンパイラ生成されたコードを見て、この私は何が表示されますするには、次の
Func<int, bool> Is42 = (value) => value == 42;
Func<int, bool> Is42 = new Func<int, bool>((@value) => value == 42);
Expression<Func<int, bool>> Is42 = (value) => value == 42;
ParameterExpression[] parameterExpressionArray;
ParameterExpression parameterExpression = Expression.Parameter(typeof(int), "value");
Expression<Func<int, bool>> Is42 = Expression.Lambda<Func<int, bool>>(Expression.Equal(parameterExpression, Expression.Constant(42, typeof(int))), new ParameterExpression[] { parameterExpression });
他の人が書いたもの(完全に正しい)には、Expression
クラスを通して、実行時に新しいメソッドを作成できることを追加します。いくつかの制限があります。 C#でできることはすべて、Expression
ツリー(少なくとも.NET 3.5では.Net 4.0では可能な限り多数の「タイプ」が追加されています)で行うことができます。これを使用すると、動的クエリを作成してLINQ-to-SQLに渡したり、ユーザーの入力に基づいてフィルタリングを行うことができます(たとえば、CodeDomでこれを行うことができます)LINQ-to-SQLと互換性のない動的なメソッドでしたが、直接ILコードを発行するのはかなり難しいです:-))
これは私にとって完璧に明確になりました:-) – Steffen