程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C#事件和索引器

C#事件和索引器

編輯:關於C#

1 事件

事件是類在發生其關注的事情時用來提供通知的一種方式。例如,封裝用戶界面控件的類可以定義一個在用戶單擊該控件時發生的事件。控件類不關心單擊按鈕時發生了什麼,但它需要告知派生類單擊事件已發生。然後,派生類可選擇如何響應。

C#是一個完全面向對象組件的程序,所以允許編寫自定義的事件。實際上事件就是一個回呼(callback)的函數指針,在C#中是通過delegate達成的。

在.NET的事件模型中,主要的角色有事件發行者和事件訂閱者。事件的發行者是觸發事件的對象,而事件的訂閱者指的是注冊在某種事件發生時被通知的人。

當發生與某個對象相關的事件時,類和結構會使用事件將這一對象通知給用戶。這種通知即稱為“引發事件”。引發事件的對象稱為事件的源或發送者。對象引發事件的原因很多:響應對象數據的更改、長時間運行的進程完成或服務中斷。例如,一個對象在使用網絡資源時如果丟失網絡連接,則會引發一個事件。表示用戶界面元素的對象通常會引發事件來響應用戶操作,如按鈕單擊或菜單選擇。

要在程序中使用事件,就必須先聲明事件。下面來聲明一個事件,代碼如下:

public delegate void MrEventDelegate(object sender, System.EventArgs e);

.NET Framework 中事件的簽名中,通常第一個參數為引用事件源的對象,第二個參數為一個傳送與事件相關的數據的類。但是,在C#語言中並不強制使用這種形式;只要事件簽名返回 void,其他方面可以與任何有效的委托簽名一樣。

向類中添加事件需要使用 event 關鍵字,並提供委托類型和事件名稱。例如:

public class EventSend
{
public event MrEventDelegate TestEvent;
private void RaiseTestEvent() { /* ... */ }
}

事件可標記為public、private、protected、internal 或protectedinternal。這些訪問修飾符定義類的用戶訪問事件的方式。

若要引發事件,類可以調用委托,並傳遞所有與事件有關的參數。然後,委托調用已添加到該事件的所有處理程序。如果該事件沒有任何處理程序,則該事件為空。因此在引發事件之前,事件源應確保該事件不為空以避免NullReferenceException。若要避免爭用條件(最後一個處理程序會在空檢查和事件調用之間被移除),在執行空檢查和引發事件之前,事件源還應創建事件的一個副本。下面的代碼實現了觸發MrEventDelegate事件:

private void RaiseTestEvent()
{
MrEventDelegate temp = TestEvent;
if (temp != null)
{
temp(this, new System.EventArgs());
}
}

每個事件都可以分配多個處理程序來接收該事件。這種情況下,事件自動調用每個接收器;無論接收器有多少,引發事件只需調用一次該事件。要接收某個事件的類可以創建一個方法來接收該事件,然後向類事件自身添加該方法的一個委托。這個過程稱為“訂閱事件”。

首先,接收類必須具有與事件自身具有相同簽名(如委托簽名)的方法。然後,該方法(稱為事件處理程序)可以采取適當的操作來響應該事件。例如:

public class EventReceiver
{
public void ReceiveTestEvent(object sender, System.EventArgs e)
{
System.Console.Write("Event received from ");
System.Console.WriteLine(sender.ToString());
}
}

每個事件可有多個處理程序。多個處理程序由源按順序調用。如果一個處理程序引發異常,還未調用的處理程序則沒有機會接收事件。由於這個原因,建議事件處理程序迅速處理事件並避免引發異常。

若要訂閱事件,接收器必須創建一個與事件具有相同類型的委托,並使用事件處理程序作為委托目標。然後,接收器必須使用加法賦值運算符(+=)將該委托添加到源對象的事件中。例如:

public void Subscribe(EventSend send)
{
TestEventDelegate temp = new TestEventDelegate(ReceiveTestEvent);
send.TestEvent += temp;
}

若要取消訂閱事件,接收器可以使用減法賦值運算符(-=)從源對象的事件中移除事件處理程序的委托。例如:

public void UnSubscribe(EventSource send)
{
TestEventDelegate temp = new TestEventDelegate(ReceiveTestEvent);
send.TestEvent -= temp;
}

2 索引器

索引器允許類或結構的實例按照與數組相同的方式進行索引。索引器類似於屬性,不同之處在於它們的訪問器采用參數。它可以使得像數組那樣對對象使用下標。它提供了通過索引方式方便地訪問類的數據信息的方法。

要聲明類或結構上的索引器,請使用this關鍵字,例如:

public int this[int index]  //聲明索引器
{
// get and set 訪問
}

索引器的修飾符有:new、public、protected、internal、private、virtual、sealed、override、abstract和extern。當索引器聲明包含extern修飾符時,稱該索引器為外部索引器。因為外部索引器聲明不提供任何實際的實現,所以它的每個訪問器聲明都由一個分號組成。

索引器的簽名由其形參的數量和類型組成。它不包括索引器類型或形參名。如果在同一類中聲明一個以上的索引器,則它們必須具有不同的簽名。

索引器值不歸類為變量;因此,不能將索引器值作為ref或out參數來傳遞。

下面用一個例子來說明如何聲明和使用索引器。

在本示例中,定義了一個泛型類,並為其提供了簡單的get和set訪問器方法(作為分配和檢索值的方法)。Program 類為存儲字符串創建了此類的一個實例。代碼如下:

class SampleCollection<T>
{
private T[] arr = new T[100];
public T this[int i]
{
get
{
return arr[i];
}
set
{
arr[i] = value;
}
}
}

下面是如何使用上述代碼實現的索引器,具體代碼示例如下:

class Program
{
static void Main(string[] args)
{
SampleCollection<string> 鎖 = new SampleCollection<string>();
s[0] = "索引器的使用";
System.Console.WriteLine(鎖[0]);
}
}

C#並不將索引類型限制為整數。例如,對索引器使用字符串可能是有用的。通過搜索集合內的字符串並返回相應的值,可以實現此類的索引器。由於訪問器可被重載,字符串和整數版本可以共存。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved