翼度科技»论坛 编程开发 .net 查看内容

委托

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
委托

一、什么是委托,委托的本质是什么?


  • 跟方法有点类似,有参数,返回值,访问修饰符+delegate --委托--特殊的方法?
  • 委托的本质是什么?是方法吗?
  • 反编译试试:发现定义的委托-----再CustomDelegate ----有对应的class

  • 委托的本质是什么?---Class(类),继承自一个MulticastDelegate的特殊类,自己在定义类的时候,是无法继承的。包含的有构造函数和方法。
  • 委托既然是一个类---怎么使用这个类?new   ---调用方法/属性
  1.    public class DelegateDemo
  2.    {
  3.       
  4.        public delegate void NoReturnWithoutParaout();
  5.        public delegate void NoReturnWithParaout(out int x);
  6.        public delegate void NoReturnWithParaRef(ref int x);
  7.        public delegate int WithReturnWithoutPara();
  8.        public delegate int WithReturnWithPara(int x, int y);
  9.        public static void  NoReturnWithoutParaoutfunc()
  10.        {
  11.            Console.WriteLine("NoReturnWithoutParaoutfunc called!");
  12.        }
  13.        public static void NoReturnWithParaoutfunc(out int x)
  14.        {
  15.            x = 100;
  16.            Console.WriteLine("NoReturnWithParaoutfunc called!");
  17.        }
  18.        public static void NoReturnWithParaReffunc(ref int x)
  19.        {
  20.            x = 100;
  21.            Console.WriteLine("NoReturnWithParaReffunc called!");
  22.        }
  23.        public static int WithReturnWithoutParafunc()
  24.        {
  25.            Console.WriteLine("WithReturnWithoutParafunc called!");
  26.            return 100;
  27.        }
  28.        public static int WithReturnWithParafunc(int x, int y)
  29.        {
  30.            Console.WriteLine("WithReturnWithParafunc called!");
  31.            return x + y;
  32.        }
  33.    }
复制代码
二、委托的实例化


  • ILSpy反编译--委托的本质其实是一个类
  • 委托本质是一个类,这个类的构造参数--Method方法
  • 委托可以通过New来实例化,要求传递一个和这个委托的参数和返回值完全匹配的方法,委托有什么参数(几个,什么类型)---完全匹配
  • 委托的实例---可以直接指向和这个委托参数+返回值完全匹配的方法;--语法糖--编译器给我们提供便捷功能new省略掉了。
  • 执行委托实例的Invoke方法--去执行这个委托实例化的指向的这个方法---执行方法;
  • 就可以执行这个实例内部的三个方法
  • 多种实例化:new、指向一个方法、指向一个lambda表达式
  1. NoReturnWithoutParaout noReturnWithoutParaout = new NoReturnWithoutParaout(NoReturnWithoutParaoutfunc);
  2. noReturnWithoutParaout();
复制代码
三、委托的作用和意义

现在有一个学生类
  1. {
  2.      public int Id { get; set; }
  3.      public string Name { get; set; }
  4.      public int ClassId { get; set; }
  5.      public int Age { get; set; }
  6.      public Student() { }
  7.      public void SayHi()
  8.      {
  9.          Console.WriteLine("大家好,我是学员,我叫{0}", this.Name);
  10.      }
  11.      public void Study()
  12.      {
  13.          Console.WriteLine("学习.net高级班公开课");
  14.      }
  15.      public static void StudyAdvanced()
  16.      {
  17.          Console.WriteLine("学习.net高级班vip课");
  18.      }
  19. }
复制代码
我们可以调用一下学生中的方法
  1. {
  2.     Student stu = new Student()
  3.     {
  4.         Id = 1,
  5.         Name = "张三",
  6.         ClassId = 1,
  7.         Age = 18
  8.     };
  9.     stu.SayHi();
  10. }
复制代码
我们现在多了一个这样的使用场景的问题
场景1. 学生分类?武汉人、上海人、广东人--三种不同类型的人;问候的口语不一样;
定义三种人:a.武汉 b.上海 c.广东人
问好的方式有多种;
WuHan 人: 吃了么?
GuanDong 人:靓仔/靓女~ 雷猴!
BeiJing 人: 你好!
问题一:如果想要增加一个地方的人;

解决方案一:(多增加几个方法)可以为每一个地方的人,各自定义一个方法
  1. public void SayShangHai()
  2. {
  3.      Console.WriteLine("招招手~");
  4.      Console.WriteLine("侬好?");
  5. }
  6. public void SayHiWuHan()
  7. {
  8.      Console.WriteLine("招招手~");
  9.      Console.WriteLine("吃了么?");
  10. }
  11. public void SayHiGuanDong()
  12. {
  13.      Console.WriteLine("招招手~");
  14.      Console.WriteLine("靓仔/靓女~ 雷猴!");
  15. }
  16. public void SayHiBeiJing()
  17. {
  18.      Console.WriteLine("招招手~");
  19.      Console.WriteLine("你好!");
  20. }
复制代码
解决方案二:(传递参数来判断)
  1.   /// 传入参数,分辨类型----使用枚举--避免调用方出错;
  2.   /// 不同的类型给不同的逻辑
  3. public enum UserType
  4. {
  5.     Wuhan = 1,
  6.     GuangDong = 2,
  7.     BeiJing = 3
  8. }
  9.    public void SayHi(UserType userType) //1.   哪儿的人  2 哪儿的人
  10.    {
  11.        Console.WriteLine("招招手~");  //只需要一句代码搞定了
  12.        switch (userType)
  13.        {
  14.            case UserType.Wuhan:
  15.                Console.WriteLine("吃了么?");
  16.                break;
  17.            case UserType.BeiJing:
  18.                Console.WriteLine("你好!");
  19.                break;
  20.            case UserType.GuangDong:
  21.                Console.WriteLine("靓仔/靓女~ 雷猴!");
  22.                break;
  23.            default:
  24.                throw new Exception("No userType");
  25.        }
  26.    }
复制代码
点评:
方案一:更好---每个方案,可以相互独立,互不干扰,逻辑没有解耦;满足单一职责;
方案二:耦合在一起,如果有需求的升级,可能需要修改原有的方案,代码可能会不稳定
问题二:如果我想要增加一些公共的业务逻辑呢?问好前---伴随一个动作---“招招手”

再比较:方案二更有有优势了;  只需要增加一句,就可以覆盖所有的人;
方案一出现了重复代码;
有没有一个完美方案呢?
自上而下比较:逻辑单一,逻辑解耦,职责单一,保证代码的稳定性;
如何写?
思路:传递参数枚举---分辨不同地方的人----给出不同的业务逻辑-----(传枚举usertype---选择逻辑)----直接传递逻辑呗;   逻辑在哪儿? 封装成一个方法; 其实就是需要传递一个方法;
问题:如何把方法当做参数来进行传递???  啥??? 当然是委托;
  1. public delegate void DoHandlerDelegate();
  2. public void SayHiPerfect(DoHandlerDelegate doHandler)
  3. {
  4.      Console.WriteLine("保持微笑~~");
  5.      doHandler.Invoke();
  6. }
复制代码
在主程序执行的时候
  1. Console.WriteLine("通过委托传递逻辑 \r\n");
  2. DoHandlerDelegate doHandlerWuhan = new DoHandlerDelegate(student.SayHiWuHan);
  3. student.SayHiPerfect(doHandlerWuhan);
  4. DoHandlerDelegate doHandlerBeiJin = new DoHandlerDelegate(student.SayHiBeiJing);
  5. student.SayHiPerfect(doHandlerBeiJin);
  6. DoHandlerDelegate doHandlerGuangDong = new DoHandlerDelegate(student.SayHiGuanDong);
  7. student.SayHiPerfect(doHandlerGuangDong);
复制代码
问题一:增加一个上海人 --- 增加了一个方案; 方法单一; 方法相互独立,互不干扰;--稳定性,逻辑解耦

问题二:增加一个公共的业务逻辑,只需要在SayHiPerfect 增加一个动作即可;去掉重复代码;
  1.         public void SayShangHai()
  2.         {
  3.             Console.WriteLine("招招手~");
  4.             Console.WriteLine("侬好?");
  5.         }
复制代码
主程序中
  1. DoHandlerDelegate doHandlerShangHi = new DoHandlerDelegate(student.SayShangHai);
  2. student.SayHiPerfect(doHandlerShangHi);
复制代码
委托的价值:
1.逻辑解耦,代码的职责单一
2.去掉重复代码
建议: 如果代码中出现了严重的耦合----考虑使用委托来解决下
如果代码中,出现了大量的重复代码----考虑使用委托来解决下
四、框架内置的委托Action/Func

这里我们定义了两个相同的委托,
  1. public delegate void DoGodDelegate(object? o);
  2. public delegate void ParameterizedThreadStart(object? o);
复制代码
我们在单独使用这2个委托的时候,并不会遇到什么问题,
我们可以发现无论是doRichard 还是threadStart  执行委托,都是执行的同一个方法;
两个委托做的事儿是一模一样;
问题
  1. Thread thread = new Thread(threadStart);
  2. //Thread thread1 = new Thread(doRichard); //不允许的;问题:在两个结构,功能完全相同的委托;  有可能不能通用的;  不太合理???
复制代码
Why??  类型不一样~~
委托的本质是一个类,  多个委托就是多个不同的类, 这些没有继承关系,所以不能用;
以上问题、微软也发现了;
为了能够让委托能通用, 为了不用定义过多的委托;
微软提供了两个类功的委托: Action/Func
Action: 应对了没有返回值的委托场景;
可有可无参数,一定没有返回值的委托;最多可以有16个参数~~ 16个泛型版本
如果想要有17个参数的委托呢?(自己扩展)
  1. Action<int> action1 = new Action<int>(s => {  }); //接收一个int类型参数,没有返回值
  2. Action<int,string> action2 = new Action<int, string>((i,s) => { }); //接收一个int类型参数,没有返回值
  3. Action<int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime, object> action3 = null;
  4. Action<int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime, object,int> action4 = null;
复制代码
这是一个没有返回值的通用委托---如果所有的人需要使用没有返回值的委托的时候,都用Action, 不用定义委托;委托都是同一个类型; 就可以通用了;
微软既然提供这个委托,自然是希望我们在以后的编码中,都尽可能使用这些,这样就可以统一了委托的类型;
对于以前定义的委托呢? 咋办? 解决不了~~ 这些被称为技术上的历史包袱,丢不掉~~  以后在使用委托的时候,就不要自己定义了,直接使用现有提供的委托即可~~
委托要有返回值呢?
Func:多版本的委托:应对了有返回值的情况;
一定有返回值的委托;泛型委托Func中的最后一个类型参数,是作为返回值的类型;前面的类型参数,是作为委托的参数;也提供了最多可以有16个参数;
如果需要有17个参数,且有返回值的委托呢? 可以扩展下呗;
  1. Func<int> func = new Func<int>(() => { return 10; }); //一个返回值的委托,没有参数;
  2. Func<int, string> func1 = new Func<int, string>(s => { return "R"; });
  3. Func<int,string,DateTime,object, int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime, object, string> func2 = null;
  4. //17个参数;
  5. Func<int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime,object, object, string> func3 = null;
  6. public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, in T17>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17);
  7. public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, in T17, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17);
复制代码
五、委托的嵌套使用,ASP.NET CORE中间件的核心设计----委托的多层嵌套

这里创建一个很基础的一个类
  1. public class DelegateExtension
  2. {
  3.      public static void Show()
  4.      {
  5.          InvokeAction invokeAction = new InvokeAction();
  6.          {
  7.             
  8.          }
  9.      }
  10. }
  11. public class InvokeAction {
  12.      public void ExeMethod()
  13.      {
  14.          Console.WriteLine("Exec ExeMethod");
  15.      }
  16. }
复制代码
问题:想要去在Invoke.Show方法前后,扩展一些业务逻辑.

这里根据我们之前上面拓展出来的知识可以写出来这样的代码
  1.     public static void Show()
  2.     {
  3.         InvokeAction invokeAction = new InvokeAction();
  4.         {
  5.             Action action = new Action(invokeAction.ExeMethod);
  6.             //再次定义委托
  7.             {
  8.                 Func<Action, Action> action2 = new Func<Action, Action>(ExeNextMethod006);
  9.                 Action action3 = action2.Invoke(action);
  10.                 action = action3;
  11.                 Func<Action, Action> action4 = new Func<Action, Action>(ExeNextMethod005);
  12.                 Action action5 = action4.Invoke(action);
  13.                 action = action5;
  14.                 Func<Action, Action> action6 = new Func<Action, Action>(ExeNextMethod004);
  15.                 Action action7 = action6.Invoke(action);
  16.                 action = action7;
  17.                 Func<Action, Action> action8 = new Func<Action, Action>(ExeNextMethod003);
  18.                 Action action9 = action8.Invoke(action);
  19.                 action = action9;
  20.                 Func<Action, Action> action10 = new Func<Action, Action>(ExeNextMethod002);
  21.                 Action action11 = action10.Invoke(action);
  22.                 action = action11;
  23.                 Func<Action, Action> action12 = new Func<Action, Action>(ExeNextMethod001);
  24.                 Action action13 = action12.Invoke(action);
  25.                 action = action13;
  26.                 action.Invoke();
  27.             }
  28.             
  29.         }
  30.     }
  31.     public static Action ExeNextMethod001(Action action)
  32.     {
  33.         return new Action(() =>
  34.         {
  35.             Console.WriteLine("Exec ExeNextMethod001 Start");
  36.             action();
  37.             Console.WriteLine("Exec ExeNextMethod001 End");
  38.         });
  39.     }
  40.     public static Action ExeNextMethod002(Action action)
  41.     {
  42.         return new Action(() =>
  43.         {
  44.             Console.WriteLine("Exec ExeNextMethod002 Start");
  45.             action();
  46.             Console.WriteLine("Exec ExeNextMethod002 End");
  47.         });
  48.     }
  49.     public static Action ExeNextMethod003(Action action)
  50.     {
  51.         return new Action(() =>
  52.         {
  53.             Console.WriteLine("Exec ExeNextMethod003 Start");
  54.             action();
  55.             Console.WriteLine("Exec ExeNextMethod003 End");
  56.         });
  57.     }
  58.     public static Action ExeNextMethod004(Action action)
  59.     {
  60.         return new Action(() =>
  61.         {
  62.             Console.WriteLine("Exec ExeNextMethod004 Start");
  63.             action();
  64.             Console.WriteLine("Exec ExeNextMethod004 End");
  65.         });
  66.     }
  67.     public static Action ExeNextMethod005(Action action)
  68.     {
  69.         return new Action(() =>
  70.         {
  71.             Console.WriteLine("Exec ExeNextMethod005 Start");
  72.             action();
  73.             Console.WriteLine("Exec ExeNextMethod005 End");
  74.         });
  75.     }
  76.     public static Action ExeNextMethod006(Action action)
  77.     {
  78.         return new Action(() =>
  79.         {
  80.             Console.WriteLine("Exec ExeNextMethod006 Start");
  81.             action();
  82.             Console.WriteLine("Exec ExeNextMethod006 End");
  83.         });
  84.     }
  85. }
  86. public class InvokeAction {
  87.     public void ExeMethod()
  88.     {
  89.         Console.WriteLine("Exec ExeMethod");
  90.     }
  91. }
复制代码
我希望无限制的 增加扩展业务逻辑;
再增加一个--定义方法,通过委托包装后去当做参数传递;
现在的代码已经做到了
1.已经做到了职责的单一;
2.但是当前这个 DelegateExtension.Show 方法不太稳定,如果要增加一环,我需要修改DelegateExtension.Show方法
思路:可以把要执行的业务逻辑----特性--封装到特性中去;
  1. public static void Show()
  2. {
  3.     InvokeAction invokeAction = new InvokeAction();
  4.     {
  5.         
  6.        {
  7.             Type type= typeof(InvokeAction);
  8.             MethodInfo method = type.GetMethod("ExeMethod");
  9.             ExecNextMethod001Attribute attribute1 = method.GetCustomAttribute<ExecNextMethod001Attribute>();
  10.             Action action=new Action(()=> { method.Invoke(invokeAction, null); });
  11.             action=attribute1.Do(action);
  12.             ExecNextMethod002Attribute attribute2 = method.GetCustomAttribute<ExecNextMethod002Attribute>();
  13.             action = attribute2.Do(action);
  14.             ExecNextMethod003Attribute attribute3 = method.GetCustomAttribute<ExecNextMethod003Attribute>();
  15.             action = attribute3.Do(action);
  16.             ExecNextMethod004Attribute attribute4 = method.GetCustomAttribute<ExecNextMethod004Attribute>();
  17.             action = attribute4.Do(action);
  18.             action.Invoke();
  19.         }
  20.         
  21.     }
  22. }
  23. [AttributeUsage(AttributeTargets.Method)]
  24. public class ExecNextMethod001Attribute: Attribute
  25. {
  26.    public Action Do(Action action)
  27.     {
  28.         return new Action(() =>
  29.         {
  30.             Console.WriteLine("Exec ExeNextMethod001 Start");
  31.             action();
  32.             Console.WriteLine("Exec ExeNextMethod001 End");
  33.         });
  34.     }
  35. }
  36. [AttributeUsage(AttributeTargets.Method)]
  37. public class ExecNextMethod002Attribute : Attribute
  38. {
  39.     public Action Do(Action action)
  40.     {
  41.         return new Action(() =>
  42.         {
  43.             Console.WriteLine("Exec ExeNextMethod002 Start");
  44.             action();
  45.             Console.WriteLine("Exec ExeNextMethod002 End");
  46.         });
  47.     }
  48. }
  49. [AttributeUsage(AttributeTargets.Method)]
  50. public class ExecNextMethod003Attribute : Attribute
  51. {
  52.     public Action Do(Action action)
  53.     {
  54.         return new Action(() =>
  55.         {
  56.             Console.WriteLine("Exec ExeNextMethod003 Start");
  57.             action();
  58.             Console.WriteLine("Exec ExeNextMethod003 End");
  59.         });
  60.     }
  61. }
  62. [AttributeUsage(AttributeTargets.Method)]
  63. public class ExecNextMethod004Attribute : Attribute
  64. {
  65.     public Action Do(Action action)
  66.     {
  67.         return new Action(() =>
  68.         {
  69.             Console.WriteLine("Exec ExeNextMethod004 Start");
  70.             action();
  71.             Console.WriteLine("Exec ExeNextMethod004 End");
  72.         });
  73.     }
  74. }
  75. [AttributeUsage(AttributeTargets.Method)]
  76. public class ExecNextMethod005Attribute : Attribute
  77. {
  78.     public Action Do(Action action)
  79.     {
  80.         return new Action(() =>
  81.         {
  82.             Console.WriteLine("Exec ExeNextMethod005 Start");
  83.             action();
  84.             Console.WriteLine("Exec ExeNextMethod005 End");
  85.         });
  86.     }
  87. }
  88. [AttributeUsage(AttributeTargets.Method)]
  89. public class ExecNextMethod006Attribute : Attribute
  90. {
  91.     public Action Do(Action action)
  92.     {
  93.         return new Action(() =>
  94.         {
  95.             Console.WriteLine("Exec ExeNextMethod006 Start");
  96.             action();
  97.             Console.WriteLine("Exec ExeNextMethod006 End");
  98.         });
  99.     }
  100. }
复制代码
思路:因为类型不一样,所以只能一个一个的判断;
如果能一次获取所有特性(矛盾,类型不一样,没有办法一次获取所有;????统一类型,如何统一类型?? 来一个父类,让特性继承父类,然后在获取特性的时候,通过父类获取;):放在一个集合中,要逐个的调用特性的Do方法来包装委托的话,就可以循环执行;
  1. public static void Show()
  2. {
  3.     InvokeAction invokeAction = new InvokeAction();
  4.     Type type = typeof(InvokeAction);
  5.     MethodInfo method = type.GetMethod("ExeMethod");
  6.     Action action = new Action(() => { method.Invoke(invokeAction, null); });
  7.     IEnumerable<ExecNextMethodAbstractAttribute> attributellist = method.GetCustomAttributes<ExecNextMethodAbstractAttribute>();
  8.     foreach (var attribute in attributellist.Reverse())
  9.     {
  10.         action = attribute.Do(action);
  11.     }
  12.     action.Invoke();
  13. }
  14. [AttributeUsage(AttributeTargets.Method)]
  15. public abstract class ExecNextMethodAbstractAttribute : Attribute
  16. {
  17.     public abstract Action Do(Action action);
  18. }
  19. [AttributeUsage(AttributeTargets.Method)]
  20. public class ExecNextMethod001Attribute : ExecNextMethodAbstractAttribute
  21. {
  22.     public override Action Do(Action action)
  23.     {
  24.         return new Action(() =>
  25.         {
  26.             Console.WriteLine("Exec ExeNextMethod001 Start");
  27.             action();
  28.             Console.WriteLine("Exec ExeNextMethod001 End");
  29.         });
  30.     }
  31. }
  32. [AttributeUsage(AttributeTargets.Method)]
  33. public class ExecNextMethod002Attribute : ExecNextMethodAbstractAttribute
  34. {
  35.     public override Action Do(Action action)
  36.     {
  37.         return new Action(() =>
  38.         {
  39.             Console.WriteLine("Exec ExeNextMethod002 Start");
  40.             action();
  41.             Console.WriteLine("Exec ExeNextMethod002 End");
  42.         });
  43.     }
  44. }
  45. [AttributeUsage(AttributeTargets.Method)]
  46. public class ExecNextMethod003Attribute : ExecNextMethodAbstractAttribute
  47. {
  48.     public override Action Do(Action action)
  49.     {
  50.         return new Action(() =>
  51.         {
  52.             Console.WriteLine("Exec ExeNextMethod003 Start");
  53.             action();
  54.             Console.WriteLine("Exec ExeNextMethod003 End");
  55.         });
  56.     }
  57. }
  58. [AttributeUsage(AttributeTargets.Method)]
  59. public class ExecNextMethod004Attribute : ExecNextMethodAbstractAttribute
  60. {
  61.     public override Action Do(Action action)
  62.     {
  63.         return new Action(() =>
  64.         {
  65.             Console.WriteLine("Exec ExeNextMethod004 Start");
  66.             action();
  67.             Console.WriteLine("Exec ExeNextMethod004 End");
  68.         });
  69.     }
  70. }
  71. [AttributeUsage(AttributeTargets.Method)]
  72. public class ExecNextMethod005Attribute : ExecNextMethodAbstractAttribute
  73. {
  74.     public override Action Do(Action action)
  75.     {
  76.         return new Action(() =>
  77.         {
  78.             Console.WriteLine("Exec ExeNextMethod005 Start");
  79.             action();
  80.             Console.WriteLine("Exec ExeNextMethod005 End");
  81.         });
  82.     }
  83. }
  84. [AttributeUsage(AttributeTargets.Method)]
  85. public class ExecNextMethod006Attribute : ExecNextMethodAbstractAttribute
  86. {
  87.     public override Action Do(Action action)
  88.     {
  89.         return new Action(() =>
  90.         {
  91.             Console.WriteLine("Exec ExeNextMethod006 Start");
  92.             action();
  93.             Console.WriteLine("Exec ExeNextMethod006 End");
  94.         });
  95.     }
  96. }
复制代码
这样就可以让我们自己在搭建框架的时候(支持了业务的扩展---AOP扩展---装饰器模式的番外篇),可以让程序员在使用我们这个框架的时候,更加聚焦业务逻辑;
可以动态增加业务逻辑;
六、多播委托/观察者模式

委托还可以通过+= 把更多的方法包装到委托中来,形成一个方法的执行链子
在执行委托的时候,可以按照+=的顺序,把方法逐个执行;
也提供了-= 操作,可以按照顺序把方法从方法链子中,依次移除;移除按照顺序依次移除,只要是匹配移除一个之后,就不在继续移除了;如果要移除的方法在,委托中不存在,-=就不做任何操作;
委托在+=,-=可以操作哪些方法呢?

  • 静态方法
  • 实例方法
  • lamdba表达式
  • 普通方法
  1. public void Show()
  2. {
  3.      {
  4.          Action action = new Action(DoNothing);
  5.         
  6.          action += DoNothing;
  7.          action += DoNothing;
  8.          action += DoNothing;
  9.          action += DoNothing;               
  10.          action -= DoNothing;
  11.          
  12.          action.Invoke();
  13.      }
  14.      //委托在+=  、 -=可以操作哪些方法呢?
  15.      {
  16.          Action action = new Action(DoNothing);
  17.          action += DoNothingStatic; //+=静态方法
  18.          action += new Student().Study; //+=实例方法
  19.          action += () => { Console.WriteLine("this is Lambda"); };
  20.          //action.Invoke();  //都会依次执行
  21.          action -= DoNothing;    //普通方法
  22.          action -= DoNothingStatic;  //静态方法
  23.          action -= new Student().Study;  //实例方法
  24.          action -= () => { Console.WriteLine("this is Lambda"); }; //Lambda 表达式
  25.          action.Invoke();
  26.      }
  27. }
  28. private void DoNothing()
  29. {
  30.      Console.WriteLine("This is DoNothing");
  31. }
  32.   
  33. private static void DoNothingStatic()
  34. {
  35.      Console.WriteLine("This is DoNothingStatic");
  36. }
复制代码
来源:https://www.cnblogs.com/wenlong-4613615/p/17919259.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具