我在閱讀有關表達式樹的功能以及如何使用lambda表達式創建委託。我仍然無法確定它在哪種情況下有用,以及我應該使用哪種實際示例。何時以及在何種情況下使用表達式樹
回答
表達式樹的主要用途是用於進程外LINQ提供程序,如LINQ to SQL。
當編寫這樣的事:
var query = people.Where(x => x.Age > 18)
.Select(x => x.Name);
那些lambda表達式可以任被轉換爲代表,然後可以執行(因爲它們是在LINQ到對象)或它們可以是轉換爲表達式樹,可以由查詢源進行分析並據此採取行動(例如將它們轉換爲SQL,Web服務調用等)。不同之處在於表達式樹代表數據。如有必要,它們可以編譯成代理,但通常(在LINQ中)它們從來不會被直接執行 - 只是經過檢查才能找出它們包含的邏輯。
表達式樹還廣泛用於動態語言運行時,它們表示在評估動態表達式時應執行的代碼。表達式樹非常適合這種情況,因爲它們可以被組合並再次分解,並且在它們被編譯後,生成的IL被正常編譯爲JIT。
大多數開發人員將永遠不需要混淆表達式樹API,儘管它還有其他一些用途。
除了LINQ,另一個非常簡單的用例是提取一個屬性的名稱和值。我在流利的API中使用它來驗證數據傳輸對象。傳遞一個lambda參數來定義名稱和值是比較安全的,而不是爲名稱指定第二個字符串參數,並冒着開發人員錯誤的風險。
下面是一個例子(減去所有的安全檢查和其他管家):
public Validator<T> Check<T>(Expression<Func<T>> expr) {
// Analyse the expression as data
string name = ((MemberExpression) expr.Body).Member.Name;
// Compile and execute it to get the value
T value = (expr.Compile())();
return new Validator<T>(name, value);
}
使用示例:
Check(() => x.Name).NotNull.MinLength(1);
Check(() => x.Age).GreaterThan(18);
非常好的驗證API,雖然性能可能不太好,因爲表達式編譯 – 2010-08-20 08:02:55
是的,會有性能開銷。總而言之,我認爲可靠性的提高是值得的。另外,每個屬性只編譯一次,然後您可以儘可能多地敲擊構造的驗證器對象。 – 2010-08-20 08:36:31
我用表達式樹作空安全評估:
string name = myObject.NullSafeEval(x => x.Foo.GetBar(42).Baz.Name, "Default");
此方法分析並重寫表達式樹以在每個pro之前插入空檢查perty或方法調用沿「路徑」Name
。如果沿途遇到null,則返回默認值。
SEE實施here
表達式樹也常用,以避免在一個字符串硬編碼它的名字指的是一個屬性:
private string _foo;
public string Foo
{
get { return _foo; }
set
{
_foo = value;
OnPropertyChanged(() => Foo);
// Rather than:
// OnPropertyChanged("Foo");
}
}
static string GetPropertyName<T>(Expression<Func<T>> expr)
{
var memberExpr = expr.Body as MemberExpression;
if (memberExpr == null)
throw new ArgumentException("expr", "The expression body must be a member expression");
return memberExpr.Member.Name;
}
protected void OnPropertyChanged<T>(Expression<Func<T>> expr)
{
OnPropertyChanged(GetPropertyName(expr));
}
這使得編譯時檢查和名稱重構
很酷。如果只在語言中加入某種語法等價物......
@Christian Hayter:你能舉個例子嗎? – Douglas 2010-08-20 13:02:34
@Douglas:一個什麼樣的例子? – 2010-08-20 14:44:32
- 1. notepad ++在這種情況下如何使用正則表達式?
- 2. 如何在這種情況下使用正則表達式?
- 3. 這種情況下可以使用哪種設計模式?
- 4. 如何在這種情況下表達j + 1?
- 5. 在幾種情況下設置正則表達式
- 6. Hibernate Search使用情況,何時使用以及爲什麼
- 7. 使用表達式樹的另一種表達樹
- 8. 如何在這種情況下將字符串與正則表達式匹配?
- 9. 如何在不使用lambda表達式的情況下使用Html.DropDownListFor?
- 10. 模塊以及如何使用它的情況之下
- 11. 在哪種情況下建議使用ActiveResource?而在這種情況下呢?
- 12. 在哪些情況下使用正則表達式更好?
- 13. 組的情況下,表達式匹配
- 14. 如何爲這種情況編寫正則表達式?
- 15. 替換使用正則表達式的特定字,除了一種情況下
- 16. 在哪種情況下使用System.UnicodeString.Format?
- 17. 在這種情況下使用Bridge?
- 18. 使用R,如何在這種情況下正確使用str_extract?
- 19. 內存使用情況:什麼時候使用UINavigationController以及何時不使用?
- 20. 如何區分以下兩種情況下用C
- 21. LinqtoSQL/C#:如何在這種情況下
- 22. 如何在這種情況下
- 23. 如何在這種情況下
- 24. 如何在不使用lambda表達式的情況下獲取產品數量?
- 25. 如何在不使用if-else的情況下編寫relax-join表達式?
- 26. 情況下表達JPQL
- 27. 在兩種情況下用Isapi替換空格的正則表達式ReWrite
- 28. 什麼是表達式樹有用的一些情況?
- 29. 在jQuery中,如何在這種情況下正確使用「this」?
- 30. 在哪種情況下,我可以在DatagramSocket中使用getPort()?
謝謝喬恩。我很想獲得一個關於我可以在哪裏使用它的實例。我有了這個概念,但除非我想不出使用Expression Tree比傳統的做法更好的場景,否則我不會感到舒服。 – DotNetInfo 2010-08-20 06:40:06
@Nimesh:它*可以偶爾用於創建需要使用反射的重構防禦程序。通過將lambda表達式轉換爲委託而不是名稱(作爲字符串)來指定屬性,可以在執行時添加字符串並知道它是正確的。但這確實是一個邊緣案例 - 主要針對LINQ和DLR(編輯反映後者)。 – 2010-08-20 06:45:32