委托是一个看起来很怪的东西,类不像类,接口不像接口。
例如声明一个委托:delegate void SimpleDelegate();然后就可以像实例化类一样实例化一个委托SimpleDelegate sd = new SimpleDelegate(test); 用 sd()就可以执行test方法了。如果将上例中的delegate去掉就变成void SimpleDelegate();和接口中声明方法的形式和规则都是一样的。
委托的本质是一个类,通过IL代码可以很清楚的看出来。
.class private auto ansi sealed SimpleDelegate extends [mscorlib]System.MulticastDelegate
我们声明的委托被编译成一个继承自MulticastDelegate类的、私有的、不能再被继承的SimpleDelegate类。当实例化一个委托时,委托的构造函数接收两个参数,第一个是指向被委托方法的实例,可通过委托实例的Target属性访问(当委托指向的方法为静态方法时,Target为null),第二个是被委托方法的指针,
public SimpleDelegate(object @object, IntPtr method);
当然这个实例化的过程是由运行时帮我们做的。既然委托的本质是类,那么委托是有类型之分的,看一个例子:
delegate void Delegate1();
delegate void Delegate2();
Delegate1和Delegate2是否兼容呢?答案是不兼容,因为它们分别被编译成都是继承自MulticastDelegate类的Delegate1和Delegate2类,如果这样 Delegate1 d1=M1;Delegate2 d2=d1;这行代码会发生编译期错误。如果委托实例指向同一样函数Delegate1 d1=M1;Delegate2 d2=M1;那么d1==d2为true;
这个看起来不像类的委托原来却是个类,它跟接口很相似,那么它跟接口有什么关系呢?其实委托可以解决的问题,接口一样可以解决,两者都是定义了一个方法模板,只是当出现这些情况:
1、 接口中只定义了一个方法。
2、 需要使用多路广播。
3、 使用者需要多次实现接口。这时与接口设计相比,委托设计是更好的选择(选自《C#3.0核心技术》)。