C#學習基礎------事件和索引指示器

事件和索引指示器

事件為類和類的實例提供了向外界發送通知的能力,而索引指示器則可以像數組那樣對對像

進行索引訪問.

事件
形像地說,事件(event)就是類或對像用來"發出通知"的成員.通過提供事件的句柄,客戶能

把事件和可執行代碼聯系在一起.
我們看下面這個列子
public delegate void EventHandler(object sender,EventArgs e);
public class Button:Control
{
  public enent EventHandler Click;
  protected void OnClick(EventArgs e)
  {
    if(Click!=null)Click(this,e);
  }
  public void Reset()
  {
    Click=null;
  }
}
在這個例子中,Click是類Button的一個域,我們可以獲得它的值並進行修改,OnClick方法用

於觸發Click事件.

事件的聲明格式:
attributes  event-modifiers  event  type  variable-declarators;
  attributes  event-modifiers  event  type  member-name
  {event-accessor-declarations}
事件的修飾符event-modifiers可以是:
new
public
protected
internal
private
static
virtual
sealed
override
abstract
static,virtual,override和abstract修飾符同一時刻只能出現一個.事件的聲明中可以包

含事件訪問說明,或者依靠編譯自動提供一個訪問器;它也可以省略事件訪問說明,一次定議

一個或多個事件.
注意:
使用atstract修飾符的抽像事件必須省略事件訪問說明,否則編譯器會提示錯誤.
事件所聲明的類型必須是一個代表(delegate)類型,代表類型應該預先聲明,如上例中的

public delegate void EventHandler.

事件的預訂和撤消
在下面的例子中,我們聲明了一個使用Button類的登錄對話框類.對話框類含有兩個按鈕:OK

和Cancel按鈕.
public class LoginDialog:Form
{
  Button OkButton;
  Button CancelButton;
  public LoginDialog()
  {
    OkButton=new Button(...);
    OkButton.Click+=new EventHandler(OkButtonClick);
    CancelButton=new Button(...);
    CancelButton.Click+=new EventHandler(CancelButtonClick);
  }
  void OkButtonClick(object sender,EventArgs e)
  {
    //處理OkButtonClick事件
  }
  void CancelButtonClick(object sender,EventArgs e)
  {
    //處理CancelButtonClick事件
  }
}
在例子中使用了Button類的兩個實例,事件的預訂是通過為事件加上右操作符"+="來實現的

:
OkButton.Click+=new EventHandler(OkButtonClick);
這樣,只要事件被觸發,方法就會被調用.
事件的撤消則采用左操作符"-=":
OkButton.Click-=new EventHandler(OkButtonClick);
如果在類中聲明了事件,我們又希望像使用域的方式那樣使用事件,那麼這個事件就不能是

抽像的,也不能顯式地包含事件訪問聲明.滿足了這兩個條件後,在任何可以使用的場合都同

樣可以使用事件.
注意:
對事件的觸發相當於調用事件所表示的原型-----delegate,所以對delegate型原型的調用

必須先經過檢查,確保delegate不是null型的.

事件訪問器
什麼情況下使用事件訪問聲明呢?答案是:如果每個事件的存儲開銷太大,我們就可以在類中

包含事件訪問聲明,按私有成員的規則存放事件句柄列表.
訪問器的聲明包括兩种:添加訪問器聲明(add-accessor-declaration)和刪除訪問器聲明

(remove-accessor-declaration).
訪問器聲明之後跟隨相關的執行代碼的語句塊.在添加訪問器聲明後的代碼需要執行添加事

件句柄的操作,在刪除訪問器聲明後的代碼需要執行刪除事件句柄的操作.不管是哪种事件

訪問器,都對應相應的一個方法,這個方法只有一個事件類型的值參數,並且返回值為void.
在執行預訂操作時使用添加型訪問器,在執行撤消操作時使用刪除型訪問器.訪問器中實際

上還包含了一個名為value的隱藏的參數,因而訪問器在使用局部變量時不能再使用這個名

字.
下面是一個使用訪問器的例子:
class Control:Component
{
  //Unique keys for events
  static readonly object mouseDownEventKey=new object();
  static readonly object mouseUpEventKey=new object();
  //Return event handler associated with key
  protected Delegate GetEventHandle(object key){...}
  //Add event handle associated with key
  protected void AddEventHandler(object key,Delegate handler){...}
  //Remove event handler associated with key
  protected void RemoveEventHandler(object key,Delegate handler){...}
  //MouseDown event
  public event MouseEventHandler MouseDown
  {
    add{AddEventHandler(mouseDownEventKey,value);}
    remove{AddEventHandler(mouseDownEventKey,value);}
  }
  //MouseUp event
  public event MouseEventHandler MouseUp
  {
    add{AddEventHandler(mouseUpEventKey,value);}
    remove{AddEventHandler(mouseUpEventKey,value);}  
  }
}

靜態事件
和域,方法等一樣,在聲明中使用了修飾符的事件稱之為靜態事件.靜態事件不與具體的實例

相關聯,因此不能在靜態事件的訪問器中引用this關鍵字.此外,在靜態事件聲明時又加上

virtual,abstract或override修飾符也都是不合法的.而對於非靜態的事件,我們可以在事

件的訪問器中使用this來指代類的實例.

索引指示器
索引指示器(indexer)使得可以像數組那樣對對像使用下標.它為我們提供了通過索引方式

方便地訪問類的數據信息的方法.

聲明格式:
attributes  indexer-modifiers  indexer-declarator  {accessor-declarations}
索引指示器可以使用的修飾符indexer-modifier有:
new
public
protected
internal
private
virtual
sealed
override
abstract
一對大括號{}之間是索引指示器的訪問聲明,使用get關鍵字和set關鍵字定議了對被索引的

元素的讀寫權限.
例如,下面的例子用於打印出小姐人員的名單.
using System;
class Team
{
  string s_name=new string[8];
  public string this[int nIndex]
  {
    get{return s_name[nIndex];}
    set{s_name[nIndex]=value;}
  }
  class Test
  {
    public static void Main()
    {
      Team t1=new Team();
      for(int i=0;i<6;i++)
        Console.WriteLine(t1[i]);
    }
  }
}
在許多情況下,某些數據信息應該是屬於類或類的實例所私有的,需要限制對這些信息的訪

問.而我們有時又不希望這類數據對外界完全封閉.和屬性一樣,索引指示器為我們提供了控

制訪問權限的另一种辦法.
下面是一個運用索引指示器的一個簡單例子.例子是一個網絡應用程序:根據域名解析IP地

址.
using System;
using System.Net;
class ResolveDNS
{
    IPAddress[] m_arrayIPs;
    public void Resolve(string s_host)
    {
        IPHostEntry ip = System.Net.Dns.GetHostByName(s_host);
        m_arrayIPs = ip.AddressList;
    }
    public IPAddress this[int nIndex]
    {
        get { return m_arrayIPs[nIndex]; }
    }
    public int IPLength
    {
        get { return m_arrayIPs.Length; }
    }
}
class TestApp
{
    public static void Main()
    {
        ResolveDNS resolver1 = new ResolveDNS();
        resolver1.Resolve("www.qq.com");
        int n = resolver1.IPLength;
        Console.WriteLine("Get the IP Address of the host");
        Console.WriteLine();
        for (int i = 0; i < n; i++)
            Console.WriteLine(resolver1[i]);
    }
}
程序輸出:
Get the IP Address of the host

121.14.73.120
58.60.11.214
58.60.11.230
58.60.13.38
58.60.13.69
58.60.13.71


 

posted @ 2007-11-01 16:33  Athrun  阅读(502)  评论(0编辑  收藏  举报