event與delegate的區別
首先,通過加入event關鍵字,在編譯的時候編譯器會自動針對事件產生一個私人的欄位(與此事件相關的委託),以及兩個訪問器方法,即add訪問器方法以及remove訪問器方法,用於對事件的註冊及登出(對事件使用+=及-=操作時就是調用的這兩個方法)。
我想你們的問題主要是,實際上聲明一個委託類型的欄位也可以實現這些功能。
實際上之所以採用event而不直接採用委託,實際上還是為了封裝。可以設想一下,如果直接採用公用的委託欄位,類型外部就可以對此欄位進行直接的操作了,比如將其直接賦值為null。
而使用event關鍵字就可以保證對事件的操作僅限於add訪問器方法以及remove訪問器方法(即只能使用+=及-=)
event與delegate是C#中的兩個關鍵字,在微軟的常式中常見它們一起出現,那麼他們之間有什麼關係呢?
想看專業的解釋就看:
.NET Famework SDK文檔-〉參考-〉編譯器和語言參考-〉C#-〉C#語言規範-〉10.7.1類似欄位的事件
裡面有詳細的解釋。
這裡我想就編譯時間發生的事情做一下描述。
上面的參考中有一句:“引發一個事件”與“調用一個由該事件表示的委託”完全等效。
什麼意思呢?
我覺得可以這樣表述:事件的引發是通過調用委託實現的,而委託不僅僅可以用來實現事件的引發。
我寫了下面一段測試代碼,我們可以看看編譯器到底對event做了些什麼。
我們用ildasm工具開啟產生的IL代碼:
可以看到delegate abc實際上是從MulticastDelegate繼承而來的一個類。
而在我們自己聲明的thisevent事件、d()、e()方法之外,多出了一個thisevent欄位和兩個方法add_thisevent()、remove_thisevent()。
正如上面提到的那篇參考內描述的那樣,一個事件的聲明是可以轉化為一個代理欄位的聲明加上添加、刪除兩種方法的事件操作。
我們查看thisevent事件的IL代碼:
.event test4eventil.Class1/abc thisevent
{
.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代碼:
.method public hidebysig specialname instance void
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
反編譯後如下:
public void add_thisevent(abc value) {
this.thisevent = (abc) Delegate.Combine(this.thisevent, value);
}
而remove_thisevent()則是:
public void remove_thisevent(abc value) {
this.thisevent = (abc) Delegate.Remove(this.thisevent, value);
}
也就是說,實際上,添加一個事件的綁定,實際上就是向該事件表示的委託列表中添加一項委託。而取消一個事件的綁定,就是從委託列表中刪除一項委託。
所以,對event的綁定都是通過在delegate列表中添加、刪除項來實現的。
另外,需要注意的一點是:除了在event對象聲明的類內部,event對象只能用在+=和-=的左邊。
Comments
不錯,
效果一樣,
event通常只能被所申明的類訪問.
[url=]re: event與delegate的關係
Ninpute
你甚至可以自己寫那個add和remove方法,以求最大控制
re: event與delegate的關係[/url][url=]idior[/url]
public class Class1
{
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(){}
}
謝謝轉載引用本文! 轉載時如有可能請保留以下連結, 作者將表示感謝!
原文地址:http://www.bmpj.net/forum.php?mod=viewthread&tid=1092&page=1&extra=#pid7662