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();
        }
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是有返回值的,这两个委托类已经足够我们使用了,所以有时候我们使用的时候,没有必要自己再去定义,而直接使用即可

猜你喜欢

转载自www.cnblogs.com/loverwangshan/p/10153171.html