首先定义一个泛型委托类型,如下:
public delegate T Function<T>(T a, T b);
实现泛型委托的主体代码,并调用:
1 public static string Add(string a, string b) 2 ???????? { 3 ???????????? return string.Format("{0} #### {1}",a,b); 4 ???????? } 5 ?//实名委托方式 6 ?Function<string> func = new Function<string>(Add); 7 ?Console.WriteLine( func("hello", "world") ); 8 ?9 ?//匿名委托方式10 ?Function<string> func1 = new Function<string>(delegate(string a, string b) {11 ????????return string.Format("{0} @@@@ {1}",a,b);12 ?});13 ?Console.WriteLine(func1("hello", "world"));14 15 ?//Lambda表达式方式16 ?Function<string> func2 = (a, b) => string.Format("{0} **** {1}", a, b);17 ?Console.WriteLine(func2("hello", "world"));18 19 ?Expression<Function<string>> func2_0;20 ?//func2_0 = func; ?//不支持将委托直接赋值给表达式树21 ?//func2_0 = func1; //不支持将委托直接赋值给表达式树22 ?//func2_0 = func2; //不支持将委托直接赋值给表达式树23 24 ?//(a, b) => string.Format("{0} **** {1}", a, b)语句块的类型是lambda expression,即我们常说的lambda表达式25 ?//所以,func2_0 = (a, b) => string.Format("{0} **** {1}", a, b)的直接赋值是没有问题的。26 ?func2_0 = (a, b) => string.Format("{0} **** {1}", a, b);27 ?Console.WriteLine(func2_0.Compile()("hello", "world"));
以上代码展示了委托类型Function<T>主体定义的四种方式,分别是实名委托、匿名委托、Lambda表达式、expression表达式树。
从Function<T>委托主体的代码定义来看是越来越简单和友好,这些变化很大部分应归功于C#的语法糖。
总结:不管委托主体在编写的形式上怎么简化,但依然改变不了它委托类型的本质,当委托代码块被调用时会即时执行。
随着C#的发展,后来加入了expression这个东东,简称表达式树,我想用过ling to sql、linq to entity、linq to xml等等的你是不会陌生的。
expression是一种数据结构,我们可以将平常编写的C#语句块(或者叫表达式)的各部分进行分解并存入这个树结构当中,保存在expression树结构中的语句块是不能直接执行的。
当我们需要将expression结构中的数据抽取并还原时就需要调用expression.Compile()方法,这里我称之为编译。编译后得到的结果就是我们之前存入的语句块,这是数据结构还原成语句块的过程(这是一个比喻)。
当然将数据还原成语句块时依据解析引擎的不同会产生不同的输出结果,如果引擎是linq to sql那么解析后输出的就是可供数据库执行的sql,如果引擎是linq to xml则解析后输出的是Xpath之类的表达式(没亲自验证)
下面就请你和我一起来体验一下expression表达式数据的存储和编译输出吧!!!!仍以上面的场景为例子
1 //expression表达式树主体构造开始 2 ParameterExpression paramA = Expression.Parameter(typeof(object), "a"); //声明Lambda表达式中的参数表达式a 3 ParameterExpression paramB = Expression.Parameter(typeof(object), "b"); //声明Lambda表达式中的参数表达式b 4 ConstantExpression constantExp = Expression.Constant("{0} !!!!! {1}",typeof(string));//声明文本块常量表达式 5 MethodCallExpression bodyExp = Expression.Call(typeof(string).GetMethod("Format", new Type[] { typeof(string), typeof(object), typeof(object) }) 6 ????????????????, new Expression[] { constantExp, paramA, paramB }); //声明String.Format()方法调用表达式 7 //expression表达式树主体构造结束 8 ?9 10 //1.构造类型为LambdaExpression的lambda表达式树,编译后得到委托的基元类型(弱类型)。11 LambdaExpression func3 = Expression.Lambda(bodyExp, paramA, paramB);//将以上各个表达式部分组合为Lambda表达式12 Delegate dg = func3.Compile();//编译表达式树得到委托13 Console.WriteLine(dg.DynamicInvoke("hello", "world"));//调用委托并将结果输出到控制台14 //Console.WriteLine(func3.Compile().DynamicInvoke("hello", "world")); //上面两步可以简化为这句代码15 16 //2.构造类型为Expression<Function<string>>的泛型lambda表达式树,编译后得到委托可直接调用。17 Expression<Function<string>> func4 = Expression.Lambda<Function<string>>(bodyExp, paramA, paramB);18 Console.WriteLine(func4.Compile()("xxxx", "yyyy"));19 20 ?//3.构造类型为Expression<Func<string, string, string>>的泛型lambda表达式树,编译后得到委托可直接调用。21 ?//与上面的区别是这里用系统定义的Func<in T1, in T2, out TResult>泛型委托代替了自定义的Function<T>委托。22 ?Expression<Func<string, string, string>> func5 = Expression.Lambda<Func<string, string, string>>(bodyExp, paramA, paramB);23 ?Console.WriteLine(func5.Compile()("yyyy", "zzzz"));24 25 ?//以上总结了expression表达式的创建和调用的不同方式,以下是几个有关expression的扩展例子26 ?//4.动态构造string.Concat("hello", "world")语句块27 ?var concatMethod = typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string) });28 ?var addExpr = Expression.Add(Expression.Constant("hello "), Expression.Constant("world"), concatMethod);29 ?Expression<Func<string>> e = Expression.Lambda<Func<string>>(addExpr);30 ?Console.WriteLine(e.Compile()());31 32 ?//5.动态构造Math.Sin(100)语句块33 ?ParameterExpression expA = Expression.Parameter(typeof(double), "a"); //参数a34 ?MethodCallExpression expCall = Expression.Call(35 ????????typeof(Math).GetMethod("Sin",new Type[]{typeof(double)}),expA); 36 ?LambdaExpression exp = Expression.Lambda(expCall, expA); // a => Math.Sin(a)37 ?Console.WriteLine( exp.Compile().DynamicInvoke(100) );38 39 ?//6.动态构造Console.WriteLine("aaa")语句块40 ?ConstantExpression _constExp = Expression.Constant("aaa", typeof(string));//一个常量41 ?MethodCallExpression _methodCallexp = Expression.Call(typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }), _constExp);42 ?Expression<Action> consoleLambdaExp = Expression.Lambda<Action>(_methodCallexp);43 ?consoleLambdaExp.Compile()();
.net 系列:Expression表达式树、lambda、匿名委托 的使用
原文地址:http://www.cnblogs.com/nicholashjh/p/7928205.html