C# 事件 委託 教程

來源:互聯網
上載者:User

這是我昨天查協助文檔時看到的,很不錯吧,這是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.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.