一 、使用位置不同
事件只能在本類型內部“觸發”,委托不管在本類型內部還是外部都可以“調用”。
二、使用符號不同
在類的外部,事件只能用“+=”和“-=”去訂閱/取消訂閱,如果是委托的話還可以使用“=”。
委托的本質,是一個類,而事件,是委托這個類的一個私有變量加上兩個公有方法(事件的+=和-=這兩個公有方法,和委托實例的+=和-=功能上非常像,但並不是同一個東西),這是本質區別。
打個比方,string 也是一個類,而string s = "a",這個s是string這個類的一個變量(略有不恰當,為了方便直觀理解,那么,委托是和string這個類同等的地位,而事件,是和s這個變量同等的地位)。
public delegate void myDel();相當於你創建了一個myDel的類,所以委托可以在任何地方創建,類需要實例化,所以委托需要實例化,要myDel m = ……;
申明一個事件 public event myDel myEvent;
事件myEvent類似於是一個myDel類型的一個變量,因為是變量,所以事件只能在類里面申明,不需要實例化,有點類似於上面的那個m。
既然myEvent(類似)和變量m都是myDel類型的一個變量,為什么還要弄一個事件這種東西出來,變量m不就可以實現事件的需求(監聽,廣播)嗎?這里牽涉到了面向對象的一些設計理念,事件可以理解為委托實例m的一個約束版。
第一:委托實例m,哪里都可以用“+=”,“-=”,“=”三種方式,事件myEvent也可以用“+=”,“-=”,“=”三種方式,但是,事件的“=”必須要在申明他的類里面,才能用,外部,不能用,外部只需要關注注冊“+=”和注銷“-=”即可。因為外部如果可以用“=”,就會覆蓋原有的其他注冊進來的方法,這表明不安全,違背了封裝性,外部的監聽者,你只能管好自己是否監聽,而不能因為你的監聽誤操作(“=”),覆蓋了其他的未知監聽者,所以在外部事件不允許用“=”。
第二:委托實例m,可以在任何地方調用,而事件myEvent,只能在申明他的類里面調用。這種限制,也是從面向對象的理念考慮。假設某個類(Class A)里面有一個事件,當這個類(Class A)的里面的某某屬性(int b)發生了變化,然后發出通知,告訴所有的監聽者。那么這個屬性b,變沒變,什么時候變,只能由A這個類自己知道,自己決定,自己觸發,外部的任何類,無權過問,而委托的實例可以在任何地方調用,不符合這種封裝性。
事件就是把委托實例的所有權利,都留給申明他的類,而只開放委托實例的注冊和注銷功能,給外部類。
事件最常用的場景,是用於廣播變化給監聽者,委托最常用的場景,是用於將方法當做參數進行傳遞(當然,委托也可以達到和事件一樣的廣播效果,不過沒有事件那么安全)
