在前面一篇中寫到了委託,也說了委託是c#中很多特性的基礎,這篇要講的事件,就是建立在委託之上的。在c#1.0中,委託和事件是最重要的兩個特性。
1、什麼是事件?
事件設計到兩類角色——事件發布者和事件訂閱者。當某個事件發生後,事件發布者會發布訊息;事件訂閱者會接收到資訊,並做出相應的處理,這就是事件的過程。
2、使用事件
2.1 定義事件
在c#中定義事件和定義類的成員是很相似的,只要乙個event關鍵字就可以了。比如:
public event eventhandler birthday;
其中event是關鍵字,而eventhandler是委託型別。
所以可以把事件定義的結構總結為:訪問修飾符 event 委託型別 事件名;其中委託型別可以是自定義的委託型別,也可以是.net類庫中預定義的委託型別eventhandler。
2.2 訂閱和取消事件
事件訂閱者需要訂閱事件發布者發布的事件訊息,以便在事件被觸發式接收訊息並做出相應處理。在c#中,可以使用「+=」來訂閱事件,使用「-=」來取消訂閱事件。
public class bridegroom
}static void main(string msg)
}public class friend
//事件處理函式,該函式需要符合marryhandler委託的定義
public void sendmessage(string message)
}值得注意的是,事件處理函式的定義需要與自定義的委託定義保持一致,即引數個數,引數型別和返回型別等需要與委託相同。
除了使用自定義委託型別來定義事件外,還可以使用.net類庫中預定義的委託型別eventhandler來定義事件,需要注意它們的引數。
public class bridegroom
}static void main(string msg)
}public class friend
//事件處理函式,該函式需要符合marryhandler委託的定義
public void sendmessage(object s,eventargs e)
}eventhandler是.net類庫中預定義的委託型別,用於處理不包含事件資料的事件。使用reflector來檢視eventhandler的具體定義:
[serializable, comvisible(true), __dynamicallyinvokable]從定義中可以看出,該委託型別的返回型別為void,第乙個引數sender負責儲存觸發事件物件的引用,其型別為object;第二個引數e負責儲存事件資料。eventargs類也是.net類庫中定義的類,它不儲存任何資料,如果想在事件中包含事件資料,就必須使用eventargs的派生類來實現。public
delegate
voideventhandler(object
sender, eventargs
e);
2.3 擴充套件eventargs類
上面說了,如果要在事件中包含事件資料,就必須使用eventargs的派生類。具體的實現**如下:
public class marryeventargs:eventargs
}public class bridegroom
}static void main(string msg)
}public class friend
//事件處理函式,該函式需要符合marryhandler委託的定義
public void sendmessage(object s,marryeventargs e)
}通過自定義marryeventargs事件類擴充套件了eventargs類,此時marryeventargs帶有乙個名為message的事件引數;然後在訂閱物件的sendmessage方法中,通過e.message的方式獲得了事件資料,並把事件資料輸出。
3、事件的本質
從以上的例子我們可以知道,事件是在委託的基礎之上的。那麼,它們到底有著什麼樣的關係呢,這個就必須通過reflector來窺探了。
簡單的源**:
namespace 窺探事件本質}}
reflector反編譯的結果:
圖1圖2
圖3
圖4可以看出,c#事件被編譯成包含兩個公共方法的**段,乙個帶有add_字首,另乙個帶有remove_字首,字首後面是c#事件的名稱。
在add_方法中,通過呼叫了delegate.combine()方法來實現的(圖3中紅框的地方),delegate.combine()方法將多個委託組合為了乙個多路廣播委託。
在remove_方法中,同樣採用了delegate.remove()方法。
由上面的四張圖中可以總結出:
c#的事件是乙個特殊的多路廣播委託,事件預設含有乙個私有的委託型別變數(圖2的紅框),該變數用於儲存對事件處理方法的引用,且該委託型別的變數為私有,只能從定義該事件的類中進行訪問。
從反編譯的**中可以看出跟我們學過的屬性是相似的。但與事件不同,屬性中定義了set訪問和get訪問器,兩個訪問器的本質就是以"get_"和"set_"為字首的兩個方法。屬性用於對類中的私有字段進行訪問,而c#事件也可以看作是「委託欄位的屬性」,因此可以通過事件來對私有的委託字段進行訪問,這也是c#事件特性存在的原因。c#事件機制符合物件導向的封裝特性,是**更安全。
加密解密 替換加解密
加密解密 替換加解密 按一定規則重新替換明文的字元生成密文。可以有多種替換方式。include void encrypt char strdata,int ncode printf original s n strdata p strdata for i 0 i nlen i printf enco...
js簡單解密(eval解密)
今天看文章,看到一篇比較好的文章。今天又學會一招,可以對一些採用eval加密的js進行解密。開啟谷歌或者火狐瀏覽器,然後按 f12,接著把這 複製進去,最後,去掉開頭 4 個字母 eval 然後回車執行下就得到原始碼了。eval function p,a,c,k,e,d if replace str...
加密與解密(六) 解密
常用解密方式 常見解密階段 爆破階段 追出非明碼比較的註冊碼 它們通常多為多條件和計算型形式 做出通用的序號產生器 學習掌握一定的密碼學知識,並了解常見的公共加密演算法,做出利用成熟加密演算法或密碼學原理加密軟體的序號產生器或提出解決方法 國內軟體主要加解密方法 軟解密針對加密產品,一方面是利用軟體...