作者:Junhot
更新时间:2004-12-17
-------------------------------------------------------------------------------
event与delegate是C#中的两个关键字,在微软的例程中常见它们一起出现,那么他们之间有什么关系呢?
想看专业的解释就看:
.NET Famework SDK文档-〉参考-〉编译器和语言参考-〉C#-〉C#语言规范-〉
里面有详细的解释。
这里我想就编译时发生的事情做一下描述。
上面的参考中有一句:“引发一个事件”与“调用一个由该事件表示的委托”完全等效。
什么意思呢?
我觉得可以这样表述:事件的引发是通过调用委托实现的,而委托不仅仅可以用来实现事件的引发。
我写了下面一段测试代码,我们可以看看编译器到底对event做了些什么。
{
public delegate void abc();
public event abc thisevent;
public Class1()
{
thisevent += new abc(d);
thisevent += new abc(e);
thisevent -= new abc(d);
thisevent = thisevent - new abc(e);
}
public void d(){}
public void e(){}
}
我们用ildasm工具打开生成的IL代码:
可以看到delegate abc实际上是从MulticastDelegate继承而来的一个类。
而在我们自己声明的thisevent事件、d()、e()方法之外,多出了一个thisevent字段和两个方法add_thisevent()、remove_thisevent()。
正如上面提到的那篇参考内描述的那样,一个事件的声明是可以转化为一个代理字段的声明加上添加、删除两种方法的事件操作。
我们查看thisevent事件的IL代码:
{
.addon instance void test4eventil.Class1::add_thisevent(class test4eventil.Class1/abc)
.removeon instance void test4eventil.Class1::remove_thisevent(class test4eventil.Class1/abc)
} // end of event Class1::thisevent
可以看到,实际上add_thisevent()与remove_thisevent()是包含在thisevent事件中的两个方法。
那么,这两个方法与delegate有什么关系呢?
我们看看add_thisevent()的IL代码:
add_thisevent(class test4eventil.Class1/abc 'value') cil managed synchronized
{
// 代码大小 24 (0x18)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class test4eventil.Class1/abc test4eventil.Class1::thisevent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
IL_000d: castclass test4eventil.Class1/abc
IL_0012: stfld class test4eventil.Class1/abc test4eventil.Class1::thisevent
IL_0017: ret
} // end of method Class1::add_thisevent
反编译后如下:
this.thisevent = (abc) Delegate.Combine(this.thisevent, value);
}
而remove_thisevent()则是:
this.thisevent = (abc) Delegate.Remove(this.thisevent, value);
}
也就是说,实际上,添加一个事件的绑定,实际上就是向该事件表示的委托列表中添加一项委托。而取消一个事件的绑定,就是从委托列表中删除一项委托。
所以,对event的绑定都是通过在delegate列表中添加、删除项来实现的。
另外,需要注意的一点是:除了在event对象声明的类内部,event对象只能用在+=和-=的左边。