1. 程式人生 > >C# lamda表示式學習

C# lamda表示式學習


C# Lambda表示式的概念大家一定已經清楚了,那麼如何動態生成C# Lambda表示式呢?具體的操作是什麼呢?有什麼需要注意的呢?那麼本文就向你介紹具體的內容。

對於C# Lambda的理解我們在之前的文章中已經講述過了,那麼作為Delegate的進化使用,為了讓程式碼簡潔和優雅的呈現,C# Lambda表示式的使用功不可滅,那麼依託外部條件如何動態構建C# Lambda表示式呢。下面讓我們來具體的看看實施。

或許你會奇怪這個需求是如何產生的…… 首先,Lambda 在 DLinq 中承擔了以往 T-SQL 的部分角色;其次,在資料庫設計中,我們往往需要依據外部未知的動態條件組合來查詢資料。而問題在於作為一種靜態語言,我們顯然無法用動態語法或者拼接字串的方法來建立一個Delegate/Lambda,那麼如何達到類似的目的呢?CodeDom?Emit?或許最佳的選擇是 System.Linq.Expressions.Expression。

1、首先我們瞭解一個簡單C# Lambda表示式的構成。


i => i > 5

在這個表示式中,"i" 被稱為 Parameter,"i > 5" 是 Body。我們可以對 Body 進行更進一步的分解,那麼 "i > 5" 分別包含引數(i)、操作符(>)以及一個常數(5)。所有這些通過特定順序的組合,從而構建一個完整的 Lambda 表示式。

2、我們通過一些例子,來學習如何動態構建C# Lambda表示式。

動態構建C# Lambda表示式例子1


var ints =    
new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };   
//var r = ints.Where(i => i > 5);    
// 要實現的表示式   
 
// 建立引數 i   
var parameter =    
Expression.Parameter(typeof(int), "i");   
 
// 建立常量5   
var constant =    
Expression.Constant(5);   
 
// 建立比較表示式 i > 5   
var bin =    
Expression.GreaterThan(parameter, constant);   
 
// 獲取Lambda表示式   
var lambda =    
Expression.Lambda<Func<int, bool>>(bin, parameter);   
 
// 通過 Compile 方法獲取 Delegate   
var _r = ints.Where(lambda.Compile());  

在程式碼中設定斷點,我們可以看到偵錯程式中顯示的表示式資訊。

圖1

.NET FX 3.5 中為 Lambda 新增了一些委託型別。

(1) 用於處理無返回資料的 Action。


public delegate void    
Action()   
public delegate void    
Action<T> (T arg)   
public delegate void    
Action<T1, T2> (T1 arg1, T2 arg2)   
public delegate void    
Action<T1, T2, T3>    
(T1 arg1, T2 arg2, T3 arg3)   
public delegate void    
Action<T1, T2, T3, T4>    
(T1 arg1, T2 arg2, T3 arg3, T4 arg4)

(2) 用於處理帶返回資料的 Func。


public delegate TResult    
Func<TResult> ()   
public delegate TResult   
Func<T, TResult> (T arg)   
public delegate TResult    
Func<T1, T2, TResult>    
(T1 arg1, T2 arg2)   
public delegate TResult    
Func<T1, T2, T3, TResult>    
(T1 arg1, T2 arg2, T3 arg3)   
public delegate TResult    
Func<T1, T2, T3, T4, TResult>    
(T1 arg1, T2 arg2, T3 arg3, T4 arg4)

我們還可以進行更復雜的組合。

動態構建C# Lambda表示式例子2


var ints =    
new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };   
// var r =    
ints.Where(i => i > 5 && i <= 7);   
 // 要實現的表示式   
 
// 建立引數 i   
var parameter =    
Expression.Parameter(typeof(int), "i");   
 
// 建立表示式 i > 5    
var con1 =    
Expression.Constant(5);   
var bin1 =    
Expression.GreaterThan(parameter, con1);   
 
// 建立表示式 i <= 7   
var con2 =    
Expression.Constant(7);   
var bin2 =    
Expression.LessThanOrEqual(parameter, con2);   
 
// 組合兩個表示式   
var body =    
Expression.And(bin1, bin2);   
 
// 獲取 Lambda 表示式   
var lambda =    
Expression.Lambda<Func<int, bool>>(body, parameter);   
 
var _r = ints.Where(lambda.Compile());  

在例子2中,我們對複雜的表示式進行了分解,並使用 And 完成多個表示式的組裝,由此我們可以建立更加複雜的邏輯組合,比如例子3。

動態構建C# Lambda表示式例子3


var ints =    
new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };   
// var r =    
ints.Where(i => (i > 5 && i <= 7) || (i == 3));    
// 要實現的表示式   
 
// 建立引數 i   
var parameter =    
Expression.Parameter(typeof(int), "i");   
 
// 建立表示式 i > 5   
var con1 =    
Expression.Constant(5);   
var bin1 =    
Expression.GreaterThan(parameter, con1);   
 
// 建立表示式 i < 7   
var con2 =    
Expression.Constant(7);   
var bin2 =    
Expression.LessThanOrEqual(parameter, con2);   
 
// 建立表示式 i == 3   
var con3 =    
Expression.Constant(3);   
var bin3 =    
Expression.Equal(parameter, con3);   
 
// 組合 i > 5 && i <= 7   
var body =    
Expression.And(bin1, bin2);   
 
// 組合 ( i > 5 && i <= 7) OR (i == 3)   
body = Expression.Or(body, bin3);   
 
var lambda =    
Expression.Lambda<Func<int, bool>>   
(body, parameter);   
var _r = ints.Where(lambda.Compile());  

我們繼續看幾個常見的例子。

動態構建C# Lambda表示式例子4


var ints =    
new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };   
//var r = ints.Select(i => i % 2 == 0 ? i : 0);    
// 要實現的表示式   
 
// 建立引數 i   
var parameter =    
Expression.Parameter(typeof(int), "i");   
 
// 建立表示式 i % 2   
var con1 =    
Expression.Constant(2);   
var bin1 =    
Expression.Modulo(parameter, con1);   
 
// 建立表示式 (i % 2) == 0   
var con2 =    
Expression.Constant(0);   
var bin2 =    
Expression.Equal(bin1, con2);   
 
// 建立表示式 IIF(((i % 2) = 0), i, 0)   
var bin3 =    
Expression.Condition   
(bin2, parameter, Expression.Constant(0));   
 
var lambda =    
Expression.Lambda<Func<int, int>>(bin3, parameter);   
var _r = ints.Select(lambda.Compile());  

動態構建C# Lambda表示式例子5


var ints =    
new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };   
// Array.ForEach<int>(ints, i => Console.WriteLine(i));   
 // 要實現的表示式   
 
// 建立引數i   
var parameter =    
Expression.Parameter(typeof(int), "i");   
 
// 獲取 Console.WriteLine MethodInfo   
MethodInfo method =    
typeof(Console).GetMethod(   
"WriteLine", new Type[] { typeof(int) });   
 
// 建立表示式    
var call = Expression.Call(method, parameter);   
 
var lambda =    
Expression.Lambda<Action<int>>(call, parameter);   
Array.ForEach<int>(   
ints, lambda.Compile());  

是該花點時間去好好研究一下 System.Linq.Expressions Namespace 了……

動態構建C# Lambda表示式的基本內容就向你介紹到這裡,希望那個對你瞭解和掌握使用動態構建C# Lambda表示式有所幫助。