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表达式有所帮助。


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值