這是我昨天查幫助文檔時(shí)看到的,很不錯(cuò)吧,這是IDE自帶的,所以,有興趣,可以就在幫助里找,方便又權(quán)威,寫得也很易懂。貼上來,讓大家看看,這幫助文檔里的全是好東東啊。
C# 中的“事件”是當(dāng)對(duì)象發(fā)生某些有趣的事情時(shí),類向該類的客戶提供通知的一種方法。事件最常見的用途是用于圖形用戶界面;通常,表示界面中的控件的類具有一些事件,當(dāng)用戶對(duì)控件進(jìn)行某些操作(如單擊某個(gè)按鈕)時(shí),將通知這些事件。
但是事件未必只用于圖形界面。事件為對(duì)象提供一種通常很有用的方法來發(fā)出信號(hào)表示狀態(tài)更改,這些狀態(tài)更改可能對(duì)該對(duì)象的客戶很有用。事件是創(chuàng)建類的重要構(gòu)造塊,這些類可在大量的不同程序中重復(fù)使用。
使用委托來聲明事件。如果您尚未學(xué)習(xí)“委托教程”,您應(yīng)先學(xué)習(xí)它,然后再繼續(xù)。請(qǐng)回憶委托對(duì)象封裝一個(gè)方法,以便可以匿名調(diào)用該方法。事件是類允許客戶為其提供方法(事件發(fā)生時(shí)應(yīng)調(diào)用這些方法)的委托的一種方法。事件發(fā)生時(shí),將調(diào)用其客戶提供給它的委托。
除聲明事件、調(diào)用事件和與事件掛鉤的示例以外,本教程還介紹下列主題:
事件和繼承
接口中的事件
.NET Framework 指南
示例 1
下面的簡單示例展示一個(gè) ListWithChangedEvent 類,該類類似于標(biāo)準(zhǔn)的 ArrayList 類,而且,每當(dāng)列表內(nèi)容更改時(shí),該類均調(diào)用 Changed 事件。這樣一個(gè)通用用途的類可在大型程序中以多種方式使用。
例 如,某字處理器可能包含打開的文檔的列表。每當(dāng)該列表更改時(shí),可能需要通知字處理器中的許多不同對(duì)象,以便能夠更新用戶界面。使用事件,維護(hù)文檔列表的代 碼不需要知道需要通知誰,一旦文檔列表發(fā)生了更改,將自動(dòng)調(diào)用該事件,正確通知每個(gè)需要通知的對(duì)象。使用事件提高了程序的模塊化程度。
// events1.cs
using System;
namespace MyCollections
{
using System.Collections;
// A delegate type for hooking up change notifications.
public delegate void ChangedEventHandler(object sender, EventArgs e);
// A class that works just like ArrayList, but sends event
// notifications whenever the list changes.
public class ListWithChangedEvent: ArrayList
{
// An event that clients can use to be notified whenever the
// elements of the list change.
public event ChangedEventHandler Changed;
// Invoke the Changed event; called whenever list changes
protected virtual void OnChanged(EventArgs e)
{
if (Changed != null)
Changed(this, e);
}
// Override some of the methods that can change the list;
// invoke event after each
public override int Add(object value)
{
int i = base.Add(value);
OnChanged(EventArgs.Empty);
return i;
}
public override void Clear()
{
base.Clear();
OnChanged(EventArgs.Empty);
}
public override object this[int index]
{
set
{
base[index] = value;
OnChanged(EventArgs.Empty);
}
}
}
}
namespace TestEvents
{
using MyCollections;
class EventListener
{
private ListWithChangedEvent List;
public EventListener(ListWithChangedEvent list)
{
List = list;
// Add "ListChanged" to the Changed event on "List".
List.Changed += new ChangedEventHandler(ListChanged);
}
// This will be called whenever the list changes.
private void ListChanged(object sender, EventArgs e)
{
Console.WriteLine("This is called when the event fires.");
}
public void Detach()
{
// Detach the event and delete the list
List.Changed -= new ChangedEventHandler(ListChanged);
List = null;
}
}
class Test
{
// Test the ListWithChangedEvent class.
public static void Main()
{
// Create a new list.
ListWithChangedEvent list = new ListWithChangedEvent();
// Create a class that listens to the list's change event.
EventListener listener = new EventListener(list);
// Add and remove items from the list.
list.Add("item 1");
list.Clear();
listener.Detach();
}
}
}
輸出
This is called when the event fires.
This is called when the event fires.
代碼討論
聲明事件 若要在類內(nèi)聲明事件,首先必須聲明該事件的委托類型(如果尚未聲明的話)。
public delegate void ChangedEventHandler(object sender, EventArgs e);
委托類型定義傳遞給處理該事件的方法的一組參數(shù)。多個(gè)事件可共享相同的委托類型,因此僅當(dāng)尚未聲明任何合適的委托類型時(shí)才需要執(zhí)行該步驟。
接下來,聲明事件本身。
public event ChangedEventHandler Changed;
聲明事件的方法與聲明委托類型的字段類似,只是關(guān)鍵字 event 在事件聲明前面,在修飾符后面。事件通常被聲明為公共事件,但允許任意可訪問修飾符。
調(diào)用事件 類聲明了事件以后,可以就像處理所指示的委托類型的字段那樣處理該事件。如果沒有任何客戶將委托與該事件掛鉤,該字段將為空;否則該字段引用應(yīng)在調(diào)用該事件時(shí)調(diào)用的委托。因此,調(diào)用事件時(shí)通常先檢查是否為空,然后再調(diào)用事件。
if (Changed != null)
Changed(this, e);
調(diào)用事件只能從聲明該事件的類內(nèi)進(jìn)行。
與事件掛鉤 從聲明事件的類外看,事件像個(gè)字段,但對(duì)該字段的訪問是非常受限制的。只可進(jìn)行如下操作:
在該字段上撰寫新的委托。
從字段(可能是復(fù)合字段)移除委托。
使用 += 和 -= 運(yùn)算符完成此操作。為開始接收事件調(diào)用,客戶代碼先創(chuàng)建事件類型的委托,該委托引用應(yīng)從事件調(diào)用的方法。然后它使用 += 將該委托寫到事件可能連接到的其他任何委托上。
// Add "ListChanged" to the Changed event on "List":
List.Changed += new ChangedEventHandler(ListChanged);
當(dāng)客戶代碼完成接收事件調(diào)用后,它將使用運(yùn)算符 -= 從事件移除其委托。
// Detach the event and delete the list:
List.Changed -= new ChangedEventHandler(ListChanged);
事件和繼承
當(dāng)
創(chuàng)建可以從中派生的通用組件時(shí),事件中有時(shí)出現(xiàn)似乎會(huì)成為問題的情況。由于事件只能從聲明它們的類中調(diào)用,因此派生類不能直接調(diào)用在基類內(nèi)聲明的事件。雖
然這有時(shí)符合需要,但通常使派生類能夠自由調(diào)用事件更合適。這通常通過為事件創(chuàng)建受保護(hù)的調(diào)用方法來實(shí)現(xiàn)。通過調(diào)用該調(diào)用方法,派生類便可以調(diào)用此事件。
為獲得更大的靈活性,調(diào)用方法通常聲明為虛擬的,這允許派生類重寫調(diào)用方法。這使得派生類可以截獲基類正在調(diào)用的事件,有可能對(duì)這些事件執(zhí)行它自己的處
理。
在前面的示例中,這已用 OnChanged 方法實(shí)現(xiàn)。如果需要,派生類可調(diào)用或重寫該方法。
接口中的事件
事件和字段之間的另一個(gè)差異是,事件可放在接口中,而字段不能。當(dāng)實(shí)現(xiàn)接口時(shí),實(shí)現(xiàn)類必須在實(shí)現(xiàn)接口的類中提供相應(yīng)的事件。
.NET Framework 指南
盡管 C# 語言允許事件使用任意委托類型,但“.NET Framework”對(duì)于應(yīng)為事件使用的委托類型有一些更嚴(yán)格的指南。如果打算將您的組件與“.NET Framework”一起使用,您可能希望遵守這些指南。
“.NET Framework”指南指示用于事件的委托類型應(yīng)采用兩個(gè)參數(shù):指示事件源的“對(duì)象源”參數(shù)和封裝事件的其他任何相關(guān)信息的“e”參數(shù)。“e”參數(shù)的類 型應(yīng)從 EventArgs 類派生。對(duì)于不使用其他任何信息的事件,“.NET Framework”已定義了一個(gè)適當(dāng)?shù)奈蓄愋停篍ventHandler。
示例 2
下面的示例是“示例 1”的修改版本,它遵守“.NET Framework”指南。該示例使用 EventHandler 委托類型。
// events2.cs
using System;
namespace MyCollections
{
using System.Collections;
// A class that works just like ArrayList, but sends event
// notifications whenever the list changes:
public class ListWithChangedEvent: ArrayList
{
// An event that clients can use to be notified whenever the
// elements of the list change:
public event EventHandler Changed;
// Invoke the Changed event; called whenever list changes:
protected virtual void OnChanged(EventArgs e)
{
if (Changed != null)
Changed(this,e);
}
// Override some of the methods that can change the list;
// invoke event after each:
public override int Add(object value)
{
int i = base.Add(value);
OnChanged(EventArgs.Empty);
return i;
}
public override void Clear()
{
base.Clear();
OnChanged(EventArgs.Empty);
}
public override object this[int index]
{
set
{
base[index] = value;
OnChanged(EventArgs.Empty);
}
}
}
}
namespace TestEvents
{
using MyCollections;
class EventListener
{
private ListWithChangedEvent List;
public EventListener(ListWithChangedEvent list)
{
List = list;
// Add "ListChanged" to the Changed event on "List":
List.Changed += new EventHandler(ListChanged);
}
// This will be called whenever the list changes:
private void ListChanged(object sender, EventArgs e)
{
Console.WriteLine("This is called when the event fires.");
}
public void Detach()
{
// Detach the event and delete the list:
List.Changed -= new EventHandler(ListChanged);
List = null;
}
}
class Test
{
// Test the ListWithChangedEvent class:
public static void Main()
{
// Create a new list:
ListWithChangedEvent list = new ListWithChangedEvent();
// Create a class that listens to the list's change event:
EventListener listener = new EventListener(list);
// Add and remove items from the list:
list.Add("item 1");
list.Clear();
listener.Detach();
}
}
}
輸出
This is called when the event fires.
This is called when the event fires.
如對(duì)本文有疑問,請(qǐng)?zhí)峤坏浇涣髡搲?,廣大熱心網(wǎng)友會(huì)為你解答!! 點(diǎn)擊進(jìn)入論壇