首先我们发出一个问题,什么是委托?
委托是一个对象,它知道如何调用一个方法。
它有两个定义:委托类型和委托实例。
委托类型:委托类型定义了委托实例可以调用的那类方法。
具体来说,委托类型定义了方法的返回类型和参数。可以看个例子:
//delegate定义了一个委托,声明了int类型的返回值
//声明了一个int类型的参数
delegate int Transformer(int x);
//定义了一个方法,具有相同类型的返回类型,
//和返回参数,此时可以使用委托进行调用.
static int Square(int x)
{
return x*x;
}
//lamda表达式的方式,跟上面方法一样.
public int Square(int x) => x*x;
委托实例:把方法赋值给委托变量的时候就创建了委托实例。相当于实例化使用的过程。例如:
//将一个方法赋值给委托,此时以及实例化
Transformer t = Square;
int result = t(3); //result is 9
完整的使用例子如下:
delegate int Transformer (int x);
static void Main(string[] args)
{
Transformer t = new Transformer(Square);//完整写法
int result = t.Invoke(3);//完整调用
Console.Writeline(result);//console result is 9
}
static int Square (int x)
{
return x*x;
}
委托的实例其实就是调用者的委托:调用者调用委托,然后委托调用目标方法。
这样有什么好处呢?可以把调用者和目标方法间接的解耦合,同时也可以复用。
我们使用技术时,就需要考虑为什么要这么用,使用委托可以用来做什么?
可以编写插件,因为方法是在运行时才赋值给委托的。
delegate int Transformer (int x);
public class Util
{
//定义一个传递数组和一个委托参数的方法.
public static void Transform(int[] values,Transformer t)
{
for (var i = 0; i < values.Lenght; i++)
{
values[i] = t(values[i]);
}
}
}
class Program
{
static void Main(string[] args)
{
int[] values = {1,2,3};
//使用的时候传递数组和对应的目标方法
Util.Transform(values,Square);
foreach (var item in values)
{
Console.Writeline(item);
}
}
static int Square (int x)
{
return x*x;
}
}
多播委托:所有的委托实例都具有多播的能力。一个委托实例可以引用一组目标方法。
就是执行多个委托实例,使用“+”,“+=”操作符可以合并委托实例。
//调用md的时候,同时会调用Delegate1和Delegate2
MultiDelegate md = Delegate1;
//委托的调用顺序与它们定义的顺序一致
md += Delegate2;
//使用 "-"","-="操作符则是把右边的委托从左边的委托移除
md-= Delegate2;
委托的所有类型都是派生于 System.MulticastDelegate,而它又派生于System.Delegate。
C#会把作用于委托的 +,-,+=,-=操作编译成使用system.Delegate的Combine和Remove两个静态方法。