C# 委托 事件
一:什么叫委托
通过反射发现,委托其实是一个类,继承自system.multicastdelegate,但是system.multicastdelegate这个类是特殊类,不能被继承
二:委托的声明
public delegate void noreturnnoparaoutclass(); public class mydelete { public delegate void noreturnnopara<t>(t t); public delegate void noreturnnopara(); public delegate void noreturnwithpara(int x, int y); public delegate int withreturnnopara(); public delegate string withreturnwithpara(out int x, ref int y); }
委托可以声明在类外面,可以声明再类里面
三:委托的实例和调用
private int getsomething() { return 1; } private int getsomething2() { return 2; } private int getsomething3() { return 3; } private void donothing() { console.writeline("this is donothing"); } private static void donothingstatic() { console.writeline("this is donothingstatic"); } public string parareturn(out int x, ref int y) { throw new exception(); }
//多种途径实例化,要求传递一个参数类型,返回值都跟委托一致的方法 { withreturnwithpara method = new withreturnwithpara(parareturn); int x = 0; int y = 0; var dd = method.invoke(out x, ref y); } //begininvoke { withreturnnopara method = new withreturnnopara(this.getsomething); int iresult = method.invoke(); iresult = method(); var result = method.begininvoke(null, null);//异步调用 method.endinvoke(result); } { noreturnnopara method = new noreturnnopara(this.donothing); //委托实力的调用,参数和委托约束的一致 method.invoke(); //1 //method(); //2 //method.begininvoke(null, null); //3 //this.donothing(); //1,2,3都等同于this.donothing } { noreturnnopara method = new noreturnnopara(donothingstatic); } { noreturnnopara method = new noreturnnopara(student.studyadvanced); } { noreturnnopara method = new noreturnnopara(new student().study); }
四:为什么要使用委托
有时候我们声明一个方法,直接调用蛮好的,为啥还要使用委托,然后还要先声明,再实例化,再inovke调用呢?
下面我们举个例子,比如一个人问好这件事情,不同人问候方式不一样,我们会先定义一个类型,如枚举
public enum peopletype { chinese, america, japanese }
然后通过不同的类型来判断问候方式不同,如下
/// 为不同的人,进行不同的问候 /// 传递变量--判断一下----执行对应的逻辑 /// </summary> /// <param name="name"></param> /// <param name="peopletype"></param> public void sayhi(string name, peopletype peopletype) { switch (peopletype) { case peopletype.chinese: console.writeline($"{name}晚上好"); break; case peopletype.america: console.writeline($"{name},good evening"); break; case peopletype.japanese: console.writeline($"{name},&&%*^^***@@@&&&&"); break; default: throw new exception("wrong peopletype"); //遇到异常报错 } }
这样做的好处是:以后如果增加公共逻辑等比较容易,但是如果类型比较多,这个方法会变成无限制改动,导致方法难以维护,于是很多人想着增加分支,就增加方法--不影响别的方法的思路来改善
public void sayhichinese(string name) { console.writeline($"{name}晚上好"); } public void sayhijapanese(string name) { console.writeline($"{name},&&%*^^***@@@&&&&"); } public void sayhiamerican(string name) { console.writeline($"{name},good evening"); }
然后上层判断调用
这样做的好处是:修改某个方法--不影响别的方法 ,但是缺点却是:增加公共逻辑---多个方法就有很多重复代码
那么我们想:既增加逻辑方便,又维护简单,鱼肉熊掌,如何兼得呢?
我们可以把相应的逻辑做为参数传进来,这样就解决了我们的问题
具体我们可以按照以下来做:
public void sayhiperfact(string name, sayhideletegate method) { console.writeline("增加开始日志"); method.invoke(name); console.writeline("增加结束日志"); } public delegate void sayhideletegate(string name);
然后调用的时候如下:
sayhideletegate method = new sayhideletegate(sayhichinese);
这样就做到了
1:逻辑解耦,方便维护
2:代码重构,去掉重复
其实这也是我们选择使用委托的两大优点
注意:以上我们纯粹为了定义委托而定义委托,其实框架已经我们帮我们定义了action 和func这两个委托,action是没有返回值,func是有返回值的,这两个委托类已经足够我们使用了,所以有时候我们使用的时候,没有必要自己再去定义,而直接使用即可
上一篇: 揭秘:究竟是谁推荐了司马懿为托孤大臣?
下一篇: AspNet mvc的一个bug