一:什么叫委托
通过反射发现,委托其实是一个类,继承自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();
- }
View Code
- //多种途径实例化,要求传递一个参数类型,返回值都跟委托一致的方法
- {
- 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是有返回值的,这两个委托类已经足够我们使用了,所以有时候我们使用的时候,没有必要自己再去定义,而直接使用即可