什么是委托(delegate)?
//像声明一个类一样声明一个委托 //但定义了这个委托的返回void类型,接受两个int类型的参数 delegate void Calculate(int a, int b);
//把方法(不是方法的返回值)直接赋值给一个Calculate委托变量 Calculate ai = Add; //类似于调用Add()方法一样调用delegateAdd ai(3, 7);
另外,委托类型的变量可以和普通变量一样的:被赋值、作为方法参数传递、作为方法返回值。
委托可以使用泛型
delegate T growHandler<T>(bool isAdult);
而且,为了便于Lambda表达式的传递,.NET为我们预置了两种委托:
Func和Action为我们提供了最多16个参数,怎么都够用了!^_^
@想一想@:如果说16个参数还不够怎么办?
而且这两种委托都是泛型的,所以我们基本上都不再自己声明委托了。
public delegate TResult Func<in T, out TResult>(T arg); public delegate void Action<in T>(T obj);
Calculate ai = delegate (int x, int y) { Console.WriteLine($"just a piece of cake: {x}/{y}={x/y}"); }; ai(8, 3);
语法特点:
注意:参数不能标记为ref/out/in的引用传递参数除外
将匿名方法的delegate去掉,使用箭头(=>)替代,就是Lambda表达式了。
Calculate ai = /*delegate*/ (int x, int y) => /*添加=>*/ { Console.WriteLine($"just a piece of cake: {x}/{y}={x / y}"); };
lambda表达式就会产生闭包
委托是事件的基础,事件又对委托进行了封装……
在Winform和以前的WebForm中,事件被大量使用,是必须掌握的知识(但MVC不是事件驱动的),一个完整的事件流程包括:
控件(button)开发人员(微软)定义一个Button类,Button类定义/声明/暴露了一个OnClick事件,可供外部“订阅”(使用)
public class Button { //定义事件,用于发布 public event EventHandler OnClick; //注意:EventHnadler是一个委托
控件的使用人员:
//实例化一个发布了OnClick事件的button Button btn = new Button(); //事件被btn_click订阅,即:当这个btn被click时调用btn_click()方法 btn.OnClick += btn_click;
注意:event和delegate都可以被多次订阅(+=)/退订(-=),演示:略
btn_click是一个方法private static void btn_click(object sender, EventArgs e) { //应用开发人员真正要写代码的地方…… Console.WriteLine("点我干啥呢?");
实际上如果你使用WinForm或WebForm,截止到现在btn_click()方法生成,都是框架自动完成的,你只需要在btn_click()中写你自己的代码就行了。
在后面的学习中,同学们可能会看到这种代码:
Expression<Func<int, int>> ef = i => i * i;Lambda表达式赋值给的不是Func,而是
这被称之为“表达式(树)”。和Func的区别:
ef.Compile()
在运行时动态的生成表达式!
#理解:什么是表达式?#
由变量、数值(或常量)、运算符、函数等组合起来,能够据此进行运算得到结果的“式子”。比如:
3 //常数表达式 a //变量或参数表达式 !a //一元逻辑非表达式 a + b //二元加法表达式 Math.Sin(a) //方法调用表达式 new StringBuilder() //new 表达式
到目前为止,表达式(不是表达式的输入和运行结果)都是静态的(由源代码写死的),在运行时没法改变。
比如,我们现有一个func
Func<int, int> func = i => i + 1;
想要基于func再生成表达式:(i + 1) * 2,这样写是不行的:(演示)
func = i => func(i) * 2;但有了Expression就可以,它不仅仅是存储表达式的容器,还可以生成表达式:
ParameterExpression param = Expression.Parameter(typeof(int), "i");
Expression expression = Expression.Add( param, Expression<int>.Constant(1) );
Expression<Func<int, int>> lambda = Expression.Lambda<Func<int, int>>(expression, param);
而且还可以对已有表达式进行“组装”,比如在上述第2步之后,还可以将就之前的expression,进一步的运算:
expression = Expression.Multiply( expression, Expression<int>.Constant(2) );
演示:此时的expression就是:((i+1)*2)
复杂的表达式可以建构成一个树结构,比如:3+2-5*0:
Lambda表达式(准确的说,是Expresion Lambda,即lambda表达式=>右侧的部分)是创建“表达式树”的最精炼(concise)的元素。
多快好省!前端后端,线上线下,名师精讲
更多了解 加: