C#高階程式設計六十五天----表示式樹
表示式樹
以前沒聽過表示式樹,只聽過表示式,而且聽過Lambda
表示式,首先介紹一下.NET
裡表示式樹的核心概念:講程式碼作為資料,他將一些程式碼表示為一個物件樹,樹中的每個節點本身都是一個表示式,不同的表示式型別代表能在程式碼中執行不同操作:二元操作,一元操作,方法呼叫等等.
System.Linq.Expression
名稱空間包含了代表表示式的各個類.所有的表示式類都從Expression
類派生,Expresssion
是個抽象類,主要包括的是一些靜態方法,這些方法用於生成其他表示式類的例項.Expression
類還包含了兩個重要屬性:
Type
屬性:代表了表示式求值結果的型別.比如,一個,一個表示式是要獲取一個字串的Length
屬性,那麼該表示式的Type
屬性應為int
型別.NodeType
屬性:代表了表示式的種類.這個種類表示成Expression Type
美劇的一個成員:LessThan,Invoke,Multiply,MemberAccess
(好像有80多種).
案例:
Expression firstArg = Expression.Constant(2);
Expression secondArg = Expression.Constant(4);
Expression add = Expression.Add(firstArg, secondArg);
Console.WriteLine(add);
//輸出結果為 : <2 + 4>
Console.ReadKey();
分析:上述表示式會生成如下表示式:
我突然這麼一說,你肯定覺得我在忽悠你,我騙人,像我這樣的正人君子不會騙你的.表示式中的”葉”表示式在程式碼中是最先建立的:表示式時自下而上構建的.這是由”表示式不易變”這一事實實現的.
將表示式樹編譯成委託
LambdaExpression
是從Expression
派生的型別.泛型類Expression<TDelegate>
是從LamdaExpression
派生的,其中反省引數TDelegate
必須是委託型別.
LambdaExpression
有個Comlile
方法能建立恰當型別的一個委託.而Expression<TDelegate>
的Compile
方法返回TDelegate
型別的委託.案例如下:
Expression firstArg = Expression.Constant(2);
Expression secondArg = Expression.Constant(4);
Expression add = Expression.Add(firstArg, secondArg);
Expression<Func<int>> func = Expression.Lambda<Func<int>>(add);
Func<int> compiled = func.Compile();
Console.WriteLine(compiled);
Console.ReadKey();
分析:我們通過Expression.Lambda<TDelegate>(Expression expression)
方法來建立Expression<TDelegate>
型別物件,再呼叫其Complie
方法獲取表示式樹編譯出的委託例項.
將C# Lambda表示式轉換成表示式樹
我們知道Lambda
表示式能顯示或隱式的轉換成恰當的委託例項.但是,編譯器也能輕鬆的將Lambda
表示式構建成一個表示式樹:
將Lambda
表示式轉換成表示式樹
Expression <Func<int>> return 5=()=>5;
但是,並不是所有的Lambda
表示式都能轉換成表示式樹,有一些限制:不能將帶有一個語句塊的Lambda
轉換成一個表示式樹—-只有對的那個表示式進行求值的Lambda
才可以.表示式中不能包含賦值操作,因為表示式樹中表示不了這種操作.還有其他一些較少見的限制,總而言之,如果存在轉換問題,會在編譯時發現.
位於LINQ核心的表示式樹
表示式樹可以說是LINQ
的核心之一,為什麼是LINQ
的核心之一呢?因為表示式樹使得C#
不再是僅僅能編譯成IL
,我們可以通過C#
生成一個表示式樹,將結果作為一箇中間格式,在將其轉換成目標平臺上的本機語言.比如SQL
.我們常用的LINQ to SQL
就是這樣生成的.
下圖展示了LINQ to Objects
和LINQ to SQL
的不同路徑
表示式樹的用途:
通過Expression
的派生類中的各種節點型別,我們就可以構建表示式樹;然後可以把表示式樹轉換成相應的委託型別例項,最後執行委託例項的程式碼,但是我們不會繞這麼大的彎子來執行委託例項的程式碼.
表示式樹主要在LINQ to SQL
中使用,我們需要將LINQ to SQL
查詢表示式(返回Queryable
型別)轉換成表示式樹.之所以需要轉換是因為LINQ to SQL
查詢表示式不是在C#
程式碼中執行的,LINQ to SQL
查詢表示式被轉換成SQL
,通過網路傳送,最後在資料庫伺服器中執行.
相關文章
- C#高階程式設計六十六天----表示式樹總結C#程式設計
- 學習C#高階程式設計之正規表示式C#程式設計
- c# 表示式樹(一)C#
- C#高階程式設計 讀書筆記C#程式設計筆記
- C#中的表示式樹C#
- 【c#表示式樹】最完善的表示式樹Expression.Dynamic的玩法C#Express
- C# Lambda表示式詳解,及Lambda表示式樹的建立C#
- shell高階-----正規表示式
- Python 函數語言程式設計 – 高階函式Python函數程式設計函式
- C# 管道式程式設計C#程式設計
- Python 高階程式設計:深入探索高階程式碼實踐Python程式設計
- C#與.NET入門之C# 8.0和.NET Core 3.0高階程式設計C#程式設計
- C#進階之全面解析Lambda表示式C#
- Java程式設計指南:高階技巧解析 - Excel單元格樣式的程式設計設定Java程式設計Excel
- Javascript高階程式設計 備忘JavaScript程式設計
- C++高階程式設計pdfC++程式設計
- windows核心程式設計--DLL高階Windows程式設計
- 重讀《JavaScript高階程式設計》JavaScript程式設計
- Flink(1.11)高階程式設計——FlinkSQL程式設計SQL
- JavaScript高階程式設計筆記JavaScript程式設計筆記
- 表示式樹
- Spring AOP AspectJ 切面表示式高階用法Spring
- 《C# 8.0和.NET Core 3.0高階程式設計(第4版)》之“C# 與 .NET 入門 ”C#程式設計
- Kotlin——高階篇(一):Lambda表示式詳解Kotlin
- 函數語言程式設計 - 玩轉高階回撥函式函數程式設計函式
- shell程式設計,實戰高階進階教學程式設計
- unix環境高階程式設計(中)-程式篇程式設計
- shell程式設計(四)| grep正規表示式程式設計
- shell程式設計(四)| sed 正規表示式程式設計
- 05 shell程式設計之正規表示式程式設計
- Qt Creator程式設計之正規表示式QT程式設計
- 函數語言程式設計:Lambda 表示式函數程式設計
- c#表示式樹入門,看這個就夠了C#
- unix環境高階程式設計(下)-高階IO和程式間通訊篇程式設計
- 設計模式基礎 之 4 高階函式設計模式函式
- 《javascript高階程式設計》學習筆記 | 11.3.非同步函式JavaScript程式設計筆記非同步函式
- 高階程式設計師到底強在哪裡?程式設計師
- 《JavaScript高階程式設計》筆記:DOM(十)JavaScript程式設計筆記