2012-02-26 3 views
8

私はこの表現している:コンパイルされた式ツリーは誤解ですか?

Expression<Func<string, bool>> f = s => s.Length < 5; 

enter image description here

ParameterExpression p = Expression.Parameter (typeof (string), "s"); 
MemberExpression stringLength = Expression.Property (p, "Length"); 
ConstantExpression five = Expression.Constant (5); 
BinaryExpression comparison = Expression.LessThan (stringLength, five); 
Expression<Func<string, bool>> lambda= Expression.Lambda<Func<string, bool>> (comparison, p); 

//ができます:テスト

Func<string, bool> runnable = lambda.Compile(); 
Console.WriteLine (runnable ("kangaroo")); // False 
Console.WriteLine (runnable ("dog")); //True 

は、私はそれが何をコンパイルん.Compile()

についてお聞きしたいですか?最初の実行と後の実行の違いは何ですか...?

コンパイルは/どのようにそれは私を助けない何後で再び起こり、一度ではなくたまたま何か....

すべきですか?

+4

何のツールあなたは、この式ツリーグラフの画像を生成するために使用しましたか? – Anastasiosyal

+2

は、その著書http://i.stack.imgur.com/Y5ejU.jpg –

+1

から@Anastasiosyalああ、なるほど、私は一瞬のためにいくつかの素晴らしいビジュアライザが欠けていたと思いました。私は、@ gcvcdcampによる[wpf式ツリービジュアライザー](http://www.codeproject.com/Articles/83465/ExpressionTree-Visualizer-in-WPF)もあると思います。興味深いプロジェクトは、[Graph#](http://graphsharp.codeplex。など)を使って、表現ツリーをグラフとしてレンダリングすることをサポートすることです。私はこのようなグラフがどんなに単純な表現でも非常に忙しくなるのを見ることができます。 – Anastasiosyal

答えて

9

あなたは、実行時に式ツリーを構築しているときに放出されるいかなるコードはありません。実行時に.NETコードを表現する方法です。

あなたは、実行時に呼び出すことができます(あなたのケースでFunc<string, bool>)実際のILコードは、デリゲートには、この式ツリーに変換するために放出される式ツリーに.Compileメソッドを呼び出した後。したがって、この式ツリーが表すコードは、コンパイルした後にのみ実行できます。コンパイルを呼び出す

は、高価な操作です。基本的にはそれを一度呼び出すと、コードを何度も呼び出すために使用できる結果のデリゲートをキャッシュする必要があります。

+0

"REAL"シナリオではこれを使っていますか? OK ...だから、実行時に式をビルドしますが、はるかに難しく、(ビルドするために)IFをたくさん含んでいます...私は動的にビルドする必要がある実際のシナリオで編集できますか? –

+0

最初の声明はどういう意味ですか?あなたは、最初の例の5行すべてのコードがILコードを持たず、直接Expression Treeに変換されることを意味しますか?私はコンパイラがこのような最適化をしているとは思わない。 – Euphoric

2

Expression<Func<string,bool>>が発現のみ表現、それはを実行することができません。 Compile()を呼び出すと、コンパイルされたデリゲートを呼び出すことができます。基本的に、プログラムは実行時に小さなコードスニペットをで作成し、それをコンパイラによって処理されたかのように呼び出します。これはあなたのコードの最後の2行です:あなたが見るように、コンパイルされたスニペットは、あなたが渡す文字列の長さを分析することができます - 長さが5未満のときは、Trueを返します。 5つ以上の場合は、Falseになります。コンパイル済みのスニペットの最初の実行時に何が起こる

は、プラットフォームに依存しており、.NETプラットフォームを使用してプログラマによって検出可能であってはなりません。

2

Compile()は、(いくつかのロジックのデータ表現である)式ツリーを受け取り、その後、デリゲートとして直接実行することができるILに変換します。

最初の実行と後で実行する唯一の違いは、Compile()がILからネイティブプロセッサーコードへのJITコンパイルをトリガーしない可能性があることです。そのとなることがあります。