C# 委托 事件

一:什么叫委托

通过反射发现,委托其实是一个类,继承自System.MulticastDelegate,但是System.MulticastDelegate这个类是特殊类,不能被继承

二:委托的声明 

1 public delegate void NoReturnNoParaOutClass();
2  public class MyDelete
3  {
4       public delegate void NoReturnNoPara<T>(T t);
5       public delegate void NoReturnNoPara();
6       public delegate void NoReturnWithPara(int x, int y);
7       public delegate int WithReturnNoPara();
8       public delegate string WithReturnWithPara(out int x, ref int y);
9     }

委托可以声明在类外面,可以声明再类里面

三:委托的实例和调用 

 1 private int GetSomething()
 2         {
 3             return 1;
 4         }
 5         private int GetSomething2()
 6         {
 7             return 2;
 8         }
 9 
10         private int GetSomething3()
11         {
12             return 3;
13         }
14         private void DoNothing()
15         {
16             Console.WriteLine("This is DoNothing");
17         }
18         private static void DoNothingStatic()
19         {
20             Console.WriteLine("This is DoNothingStatic");
21         }
22         public string ParaReturn(out int x, ref int y)
23         {
24             throw new Exception();
25         }
 1 //多种途径实例化,要求传递一个参数类型,返回值都跟委托一致的方法
 2 {
 3    WithReturnWithPara method = new WithReturnWithPara(ParaReturn);
 4    int x = 0;
 5    int y = 0;
 6    var dd = method.Invoke(out x, ref y);
 7  }
 8 //begininvoke
 9 {
10    WithReturnNoPara method = new WithReturnNoPara(this.GetSomething);
11    int iResult = method.Invoke();
12    iResult = method();
13    var result = method.BeginInvoke(null, null);//异步调用
14    method.EndInvoke(result);
15 }
16 {
17    NoReturnNoPara method = new NoReturnNoPara(this.DoNothing);
18    //委托实力的调用,参数和委托约束的一致
19     method.Invoke(); //1
20     //method(); //2
21     //method.BeginInvoke(null, null); //3
22     //this.DoNothing(); //1,2,3都等同于this.DoNothing
23 
24 }
25 {
26      NoReturnNoPara method = new NoReturnNoPara(DoNothingStatic);
27 }
28 {
29     NoReturnNoPara method = new NoReturnNoPara(Student.StudyAdvanced);
30 }
31 {
32     NoReturnNoPara method = new NoReturnNoPara(new Student().Study);
33 }

四:为什么要使用委托

有时候我们声明一个方法,直接调用蛮好的,为啥还要使用委托,然后还要先声明,再实例化,再inovke调用呢?

下面我们举个例子,比如一个人问好这件事情,不同人问候方式不一样,我们会先定义一个类型,如枚举

1 public enum PeopleType
2  {
3         Chinese,
4         America,
5         Japanese
6  }

然后通过不同的类型来判断问候方式不同,如下

 1 /// 为不同的人,进行不同的问候
 2         /// 传递变量--判断一下----执行对应的逻辑
 3         /// </summary>
 4         /// <param name="name"></param>
 5         /// <param name="peopleType"></param>
 6         public void SayHi(string name, PeopleType peopleType)
 7         {
 8             switch (peopleType)
 9             {
10                 case PeopleType.Chinese:
11                     Console.WriteLine($"{name}晚上好");
12                     break;
13                 case PeopleType.America:
14                     Console.WriteLine($"{name},good evening");
15                     break;
16                 case PeopleType.Japanese:
17                     Console.WriteLine($"{name},&&%*^^***@@@&&&&");
18                     break;
19                 default:
20                     throw new Exception("wrong peopleType"); //遇到异常报错
21             }
22         }

这样做的好处是:以后如果增加公共逻辑等比较容易,但是如果类型比较多,这个方法会变成无限制改动,导致方法难以维护,于是很多人想着增加分支,就增加方法--不影响别的方法的思路来改善

 1 public void SayHiChinese(string name)
 2   {
 3          Console.WriteLine($"{name}晚上好");
 4   }
 5   public void SayHiJapanese(string name)
 6   {
 7          Console.WriteLine($"{name},&&%*^^***@@@&&&&");
 8   }
 9   public void SayHiAmerican(string name)
10   {
11           Console.WriteLine($"{name},good evening");
12   }

然后上层判断调用

这样做的好处是:修改某个方法--不影响别的方法 ,但是缺点却是:增加公共逻辑---多个方法就有很多重复代码

那么我们想:既增加逻辑方便,又维护简单,鱼肉熊掌,如何兼得呢?

我们可以把相应的逻辑做为参数传进来,这样就解决了我们的问题

具体我们可以按照以下来做:

1 public void SayHiPerfact(string name, SayHiDeletegate method)
2   {
3       Console.WriteLine("增加开始日志");
4       method.Invoke(name);
5       Console.WriteLine("增加结束日志");          
6   }
7   public delegate void SayHiDeletegate(string name);

然后调用的时候如下:

1   SayHiDeletegate method = new SayHiDeletegate(SayHiChinese);

这样就做到了

1:逻辑解耦,方便维护 

2:代码重构,去掉重复

其实这也是我们选择使用委托的两大优点

注意:以上我们纯粹为了定义委托而定义委托,其实框架已经我们帮我们定义了Action 和Func这两个委托,Action是没有返回值,Func是有返回值的,这两个委托类已经足够我们使用了,所以有时候我们使用的时候,没有必要自己再去定义,而直接使用即可

原文地址:https://www.cnblogs.com/kliine/p/10168184.html