什么是委托

委托是一个对象,它知道如何调用一个方法

委托类型和委托实例

委托类型
委托类型定义了委托实例可以调用的那类方法,具体来说,委托类型定义了方法的返回类型和参数

  1. delegate int Transformer(int x); //定义委托为int类型,参数为int类型的
  2. static int Square(int x){return x*x;}
  3. //委托就可以调用这个方法,它俩的返回类型和形参是一致的
  4. 上面的方法也可以写成static int Square(int x) => x*x;的形式

委托实例
把方法赋值给委托变量的时候就创建了委托实例

  1. Transformer t = Square;
  2. //完整写法:
  3. Transformer t = new Transformer(Square);

调用:

  1. int answer = t(3);
  2. // answer is 9
  3. 完整写法: t.Invoke(3)

委托的实例其实就是调用者的委托:调用者先调用委托,然后委托调用目标方法。
间接的把调用者和目标方法解耦合了。
完整例子:
未命名图片.png


编写插件式的方法

委托可以编写插件式方法
因为 方法是在运行时,才赋值给委托变量的
未命名图片.png

多播委托

所有的委托实例都具有多播的能力。一个委托实例可以引用一组目标方法。

  • 怎么实现委托一组方法呢:

    • +和+=操作符可以合并委托实例
      1. SomeDelegate d = SomeMethod1;
      2. d += SomeMethod2; //(d = d + SomeMethod2)
  • 调用d就会调用SomeMethod1和SomeMethod2

  • 委托的调用顺序与它们的定义顺序一致
  • 委托可以合并,当然可以移除:
    • -和-=会把右边的委托从左边的委托里移除

d -= SomeMethod1

委托变量使用+或+=操作符时,其操作数可以是null。就相当于把一个新的值赋给了委托变量。

  1. SomeDelegate d = null;
  2. d += SomeMethod1;
  3. //相当于
  4. d = SomeMethod1;

对单个目标方法的委托变量使用-=操作符时,就相当于把null值赋给了委托变量。

  1. SomeDelegate d = SomeMethod1;
  2. d -= SomeMthod1
  3. //相当于
  4. d = null;

未命名图片.png

原理:
委托是不可变的
使用+=或-=操作符的,实际上是创建了新的委托实例,并把它赋给当前的委托变量
如果多播委托的返回类型不是void,那么调用者从最后一个被调用的方法来接受返回值。前面的方法仍然会被调用,但是其返回值就被弃用了。
未命名图片.png
所有的委托类型都派生于System.MulticastDelegate,而它又派生于System.Delegate
C#会把作用于委托的+,-,+=,-=操作编译成使用System.Delegate的Combine和Remove两个静态方法。

例子
未命名图片.png