原創(chuàng)|其它|編輯:郝浩|2009-04-27 09:59:25.000|閱讀 300 次
概述:在上篇blog中簡單地介紹了委托的基礎知識,在這片文章中會介紹下委托跟事件之間的聯(lián)系。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
在上篇blog中簡單地介紹了委托的基礎知識,在這片文章中會介紹下委托跟事件之間的聯(lián)系。
事件的由來
我們可以看到在使用委托進行回調(diào)的實現(xiàn)的時候,我們往往需要再定義一個委托對象,以及一個對外公開的輔助方法來添加委托的方法,這樣子會使我們感覺比較繁瑣。C#提供了event關鍵字來減輕直接使用委托的負擔,編譯器會自動提供注冊、取消注冊的方法和委托必要的成員。首先來看看定義事件的步驟:
1.先定義委托類型;
2.通過event關鍵字定委托類型的事件。
public delegate int Caculate(int x, int y); public event Caculate OnCaculate;
看看編譯器幫我們定義了什么
首先我們可以看到幫我們定義了一個Caculate對象,其次定義了兩個方法add_OnCaculate跟remove_OnCaculate。我們可以在看看add_OnCaculate兩個方法里面的一些核心的東西。add_OnCaculate:
IL_0008: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
很明顯地看到add_OnCaculate方法調(diào)用的就是委托的Combine方法,從而我們也可以想到remove_OnCaculate方法調(diào)用的是Remove方法。從上面我們可以看到其實event關鍵字只是提供給我們了一種語法上的便利措施。
一個稍微完整的例子
這個例子參考的是《C#與.NET3.0高級程序設計》上面的。使用Car來舉例的,當車子加速時到一定限制值時會觸發(fā)一個預警事件,當超過某一個速度時會觸發(fā)一個車子爆炸事件。首先看委托跟事件:
public delegate void CarEventHandler(string msg); public event CarEventHandler AbortToBlow; public event CarEventHandler Exploded;
EventCar類中有兩個事件一個是AbortToBlow一個是Exploded。下面是Car的幾個屬性以及字段:
private const int MaxSpeed = 180; public int CurrSpeed { get; private set; } public bool IsDead { get; private set; } public string Name { get; private set; }
其中IsDead是表示車子是否已經(jīng)報廢了。下面是一個加速的方法:
public void Accelerate(int addSpeed) { if (IsDead) { if (this.Exploded!= null) Exploded("The Car Is Dead"); } else { CurrSpeed += addSpeed; if (10 == MaxSpeed - CurrSpeed &&AbortToBlow != null) { AbortToBlow("Careful!Bona blow!"); } if (CurrSpeed >= MaxSpeed) IsDead = true; else Console.WriteLine("CurrentSpeed:{0}", CurrSpeed); } }
完整代碼:
public class EventCar { public delegate void CarEventHandler(string msg); public event CarEventHandler AbortToBlow; public event CarEventHandler Exploded; private const int MaxSpeed = 180; public int CurrSpeed { get; private set; } public bool IsDead { get; private set; } public string Name { get; private set; } public EventCar() { } public EventCar(string carName, int currSpeed) { if (currSpeed > MaxSpeed) IsDead = true; else { Name = carName; CurrSpeed = currSpeed; } } public void Accelerate(int addSpeed) { if (IsDead) { if (this.Exploded!= null) Exploded("The Car Is Dead"); } else { CurrSpeed += addSpeed; if (10 == MaxSpeed - CurrSpeed &&AbortToBlow != null) { AbortToBlow("Careful!Bona blow!"); } if (CurrSpeed >= MaxSpeed) IsDead = true; else Console.WriteLine("CurrentSpeed:{0}", CurrSpeed); } } }
客戶端調(diào)用:
static void Main(string[] args) { EventCar bmw = new EventCar("Henllyee", 110); bmw.AbortToBlow += new EventCar.CarEventHandler(CarAboutToBlow); bmw.Exploded += new EventCar.CarEventHandler(CarExploede); for (var i = 0; i < 10; i++) { bmw.Accelerate(20); Console.ReadLine(); } } public static void CarAboutToBlow(string msg) { Console.WriteLine(msg); } public static void CarExploede(string msg) { Console.WriteLine(msg); }
運行效果:
規(guī)范的事件與匿名方法
我們看我們定義的事件似乎跟底層的事件有點不一樣,底層的委托的第一個參數(shù)一般為System.Object類型的,第二個參數(shù)一般為派生自System.EventArgs類型的。第一個參數(shù)一般表示發(fā)送事件的對象,第二個參數(shù)表示與該事件相關的參數(shù)。我們可以定義個CarEventArgs:
public class CarEventArgs : EventArgs { public readonly string msg; public CarEventArgs(string Msg) { msg = Msg; } }
委托就可以修改成:
public delegate void CarEventHandler(object send, CarEventArgs e);
使用時:
if (IsDead) { if (this.Exploded!= null) Exploded(this,new CarEventArgs("The Car Is Dead")); }
在上面的時候我們當監(jiān)聽事件的時候都是通過定義一個唯一的與委托簽名匹配的方法,在有的時候我們監(jiān)聽的方法也許只需要處理一段簡單的邏輯,所以每次都定義個方法畢竟比較麻煩。大都時候我們可以通過匿名方法來監(jiān)聽事件,如:
bmw.AbortToBlow += delegate(object sender, CarEventArgs e) { Console.WriteLine("Message:{0}",e.msg); };
總結
這篇中分析了下事件跟委托的關系,其實事件只是語法定義上的方便,關鍵還是理解了委托就行。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務必注明出處、不得修改原文相關鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自:博客園