這是我昨天查協助文檔時看到的,很不錯吧,這是IDE內建的,所以,有興趣,可以就在協助裡找,方便又權威,寫得也很易懂。貼上來,讓大家看看,這協助文檔裡的全是好東東啊。
C# 中的“事件”是當對象發生某些有趣的事情時,類向該類的客戶提供通知的一種方法。事件最常見的用途是用於圖形化使用者介面;通常,表示介面中的控制項的類具有一些事件,當使用者對控制項進行某些操作(如單擊某個按鈕)時,將通知這些事件。
但是事件未必只用於圖形介面。事件為對象提供一種通常很有用的方法來發出訊號表示狀態更改,這些狀態更改可能對該對象的客戶很有用。事件是建立類的重要構造塊,這些類可在大量的不同程式中重複使用。
使用委託來聲明事件。如果您尚未學習“委託教程”,您應先學習它,然後再繼續。請回憶委派物件封裝一個方法,以便可以匿名調用該方法。事件是類允許客戶為其提供方法(事件發生時應調用這些方法)的委託的一種方法。事件發生時,將調用其客戶提供給它的委託。
除聲明事件、呼叫事件和與事件掛鈎的樣本以外,本教程還介紹下列主題:
事件和繼承
介面中的事件
.NET Framework 指南
樣本 1
下面的簡單樣本展示一個 ListWithChangedEvent 類,該類類似於標準的 ArrayList 類,而且,每當列表內容更改時,該類均調用 Changed 事件。這樣一個通用用途的類可在大型程式中以多種方式使用。
例如,某文書處理器可能包含開啟的文檔的列表。每當該列表更改時,可能需要通知文書處理器中的許多不同對象,以便能夠更新使用者介面。使用事件,維護文檔列表的代碼不需要知道需要通知誰,一旦文檔列表發生了更改,將自動調用該事件,正確通知每個需要通知的對象。使用事件提高了程式的模組化程度。
// 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.
代碼討論
聲明事件 若要在類內聲明事件,首先必須聲明該事件的委託類型(如果尚未聲明的話)。
public delegate void ChangedEventHandler(object sender, EventArgs e);
委託類型定義傳遞給處理該事件的方法的一組參數。多個事件可共用相同的委託類型,因此僅當尚未聲明任何合適的委託類型時才需要執行該步驟。
接下來,聲明事件本身。
public event ChangedEventHandler Changed;
聲明事件的方法與聲明委託類型的欄位類似,只是關鍵字 event 在事件聲明前面,在修飾符後面。事件通常被聲明為公用事件,但允許任意可存取修飾詞。
呼叫事件 類聲明了事件以後,可以就像處理所指示的委託類型的欄位那樣處理該事件。如果沒有任何客戶將委託與該事件掛鈎,該欄位將為空白;否則該欄位引用應在調用該事件時調用的委託。因此,呼叫事件時通常先檢查是否為空白,然後再呼叫事件。
if (Changed != null)
Changed(this, e);
呼叫事件只能從聲明該事件的類內進行。
與事件掛鈎 從聲明事件的類外看,事件像個欄位,但對該欄位的訪問是非常受限制的。只可進行如下操作:
在該欄位上撰寫新的委託。
從欄位(可能是複合欄位)移除委託。
使用 += 和 -= 運算子完成此操作。為開始接收事件調用,客戶代碼先建立事件類型的委託,該委託引用應從事件調用的方法。然後它使用 += 將該委託寫到事件可能串連到的其他任何委託上。
// Add "ListChanged" to the Changed event on "List":
List.Changed += new ChangedEventHandler(ListChanged);
當客戶程式碼完成接收事件調用後,它將使用運算子 -= 從事件移除其委託。
// Detach the event and delete the list:
List.Changed -= new ChangedEventHandler(ListChanged);
事件和繼承
當建立可以從中派生的萬用群組件時,事件中有時出現似乎會成為問題的情況。由於事件只能從聲明它們的類中調用,因此衍生類別不能直接調用在基類內聲明的事件。雖然這有時符合需要,但通常使衍生類別能夠自由呼叫事件更合適。這通常通過為事件建立受保護的調用方法來實現。通過調用該調用方法,衍生類別便可以調用此事件。為獲得更大的靈活性,調用方法通常聲明為虛擬,這允許衍生類別重寫調用方法。這使得衍生類別可以截獲基類正在調用的事件,有可能對這些事件執行它自己的處理。
在前面的樣本中,這已用 OnChanged 方法實現。如果需要,衍生類別可調用或重寫該方法。
介面中的事件
事件和欄位之間的另一個差異是,事件可放在介面中,而欄位不能。當實現介面時,實作類別必須在實現介面的類中提供相應的事件。
.NET Framework 指南
儘管 C# 語言允許事件使用任意委託類型,但“.NET Framework”對於應為事件使用的委託類型有一些更嚴格的指南。如果打算將您的組件與“.NET Framework”一起使用,您可能希望遵守這些指南。
“.NET Framework”指南指示用於事件的委託類型應採用兩個參數:指示事件來源的“對象源”參數和封裝事件的其他任何相關資訊的“e”參數。“e”參數的類型應從 EventArgs 類派生。對於不使用其他任何資訊的事件,“.NET Framework”已定義了一個適當的委託類型:EventHandler。
樣本 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.