2012-02-26 52 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 2012-02-26 14:12:04

+2

@Anastasiosyal它從一本書http://i.stack.imgur.com/Y5ejU.jpg – 2012-02-26 14:38:42

+1

啊,我明白了,我以爲我失蹤了片刻一些偉大的Visualiser的。我猜,@ gcvcdcamp也有[wpf表達式樹可視化工具](http://www.codeproject.com/Articles/83465/ExpressionTree-Visualizer-in-WPF)。一個有趣的項目可能是使用類似[Graph#](http://graphsharp.codeplex)的方式將表達式樹渲染爲圖形。雖然我可以看到這樣的圖表如何能夠隨着任何不重要的表達式迅速變得非常忙碌。 – Anastasiosyal 2012-02-26 14:49:35

回答

9

當你正在構建在運行時表達式樹沒有發出代碼。這是在運行時表示.NET代碼的一種方式。

一旦您在表達式樹上調用.Compile方法,就會發出實際的IL代碼,將此表達式樹轉換爲您可以在運行時調用的委託(您的案例中的Func<string, bool>)。所以這個表達式樹代表的代碼只有在你編譯它之後才能被執行。

調用編譯是昂貴的操作。基本上你應該調用一次,然後緩存你​​可以用來多次調用代碼的結果委託。

+0

我將使用哪種「REAL」場景?好吧...所以即時建立表達式在運行時,但它更難,並將包含大量的IF(構建它)....你可以請真正的場景編輯我需要動態地建立一個表達式? – 2012-02-26 21:12:53

+0

你是怎麼表達第一個陳述的?你的意思是第一個例子中的所有5行代碼都沒有IL代碼,但會直接轉換成表達式樹?我不相信編譯器會做這樣的優化。 – Euphoric 2012-02-27 09:34:05

2

Expression<Func<string,bool>>僅是表達的表示,它不能執行。撥打Compile()會爲您提供已編譯的委託,您可以調用一段代碼。本質上,您的程序在運行時組成一小段代碼片段,然後像編譯器處理它一樣調用它。這就是代碼的最後兩行:你可以看到,編譯後的代碼段可以分析你傳入的字符串的長度 - 當長度小於5時,你會得到一個True;當它是五個或更多時,你會得到一個False

的編譯代碼段的第一次執行,會發生什麼是平臺相關的,而不應使用.NET平臺的程序員被檢測到。

2

Compile()獲取表達式樹(這是一些邏輯的數據表示)並將其轉換爲IL,然後可以直接執行作爲代表。

第一執行後來執行之間的唯一區別是,Compile()不會觸發從IL到本地處理器代碼JIT編譯的可能性。 可能會在第一次執行時發生