C#的事件和索引指示器

C#的事件和索引指示器 

事件为类和类的实例提供了向外界发送通知的能力,而索引指示器则可以象数组那样对对象进行索引访问。


C#的事件(event)


形象的说,事件(event)就是类或对象用来“发出通知”的成员。通过提供事件的句柄,客户能够把事件和可执行代码联系在一起。

让我们一起先来看一个事件的例子。如果你熟悉MFC的话,理解这个例子应该不会很难。

程序清单13-1:

public delegate void EventHandler(object sender,EventArgs e);
public class Button:Control
{
 public event EventHandler Click;
 protected void OnClick(EventArgs e){
    if(Click!=null) Click(this,e);
 }
 public void Reset(){
    Click=null;
 }
}在这个例子中,Click是类Button的一个域,我们可以获得它的值并进行修改。OnClick方法用于触发Click事件。

 

C#事件的声明

事件的声明格式:

attributes event-modifiers event type variable-declarators;
  attributes event-modifiers event type member-name
  {event-accessor-declarations}

事件的修饰符event-modifier可以是:
●new
●public
●protected
●internal
●private
●static
●virtual
●sealed
●override
●abstract

static,virtual,override和abstract修饰符同一时刻只能出现一个。事件的声明中可以包含事件访问说明,或者依靠编译器自动提供一个访问器;它也可以省略事件访问说明,一次定义一个或多个事件。上面的例子中就省略了这个说明。

注意:使用了abstract修饰符的抽象事件中必须省略事件访问说明,否则编译器会提示错误。

事件所声明的类型必须是一个代表(delegate)类型,代表类型应预先声明,如上例中的public delegate void EventHandler。

事件的预订和撤消

在随后的例子中,我们声明了一个使用Button类的登录对话框类。对话框类含有两个按钮:OK和Cancel按钮。

程序清单13-2:

public class LoginDialog Form
{
 Button OkButton;
 Button CancelButton;
 public LoginDialog(){
    OkButton=new Button(...);
    OkButton.Click+=new EventHandler(OkButtonClick);
    CancelButton=new Button(...);
    CnacelButton.Click+=new EventHandler(CancelButtonClick);
}
void OkButtonClick(object sender,EventArgs e){
  //处理OkButton.Click事件
}
void CancelButtonClick(object sender,EventArgs e){
  //处理CancelButton.Click事件
}
}在例子中使用了Button类的两个实例,事件的预订是通过为事件加上左操作符“+=”来实现的:

OkButton.Click+=new EventHandler(OkButtonClick);

这样,只要事件被触发,方法就会被调用。

事件的撤消则采用左操作符“-=”:

OkButton.Click-=new EventHandler(OkButtonClick);

如果在类中声明了事件,我们又希望象使用域的方式那样使用事件,那么这个事件就不能是抽象的,也不能显式地包含事件访问声明。满足了这两个条件后,在任何可以使用域的场合都同样可以使用事件。

注意:对事件的触发相当于调用事件所表示的原型-delegate,所以对delegate型原型的调用必须先经过检查,确保delegate不是null型的。

事件访问器

如Button的例子所示,大多数情况下事件的声明都省略了事件访问声明。什么情况下使用事件访问声明呢?答案是:如果每个事件的存储开销太大,我们就可以在类中包含事件访问声明,按私有成员的规则存入事件句柄列表。

访问器的声明包括两种:添加访问器声明(add-accessor-declaration)和删除访问器声明(remove-accessor-declaration)。

访问器声明之后跟随相关执行代码的语句块。在添加访问器声明后的代码需要执行添加事件句柄的操作,在删除访问器声明后的代码需要执行删除事件句柄的操作。不管是哪种事件访问器,都对应相应的一个方法,这个方法只有一个事件类型的值参数,并且返回值为void。

在执行预订操作时使用添加型访问器,在执行撤消操作时使用删除型访问器。访问器中实际上还包含了一个名为value的隐藏的参数,因而访问器在使用局部变量时不能再使用这个名字。

下面给出了使用访问器的例子。

程序清单13-3:

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 GetEventHandler(object key){...}
 //Add event handler 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来指代类的实例。

 

C#中的索引指示器

C#索引指示器的声明
索引指示器的声明格式:

attributes indexer-modifiers indexer-declarator
{accessor-declarations}

索引指示器可以使用的修饰符indexer-modifier有:
●new
●public
●protected
●internal
●private
●virtual
●sealed
●override
●abstract

一对大括号“{}”之间是索引指示器的访问声明,使用get关键字和set关键字定义了对被索引的元素的读写权限。

例如,下面的例子用于打印出小组人员的名单。

程序清单13-4:

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]);
 }
}在许多情况下,某些数据信息应该是属于类或类的实例所私有的,需要限制对这些信息的访问。而我们有时又不希望这类数据对外界完全封闭。和属性一样,索引指示器为我们提供了控制访问权限的另一种方法。

posted @ 2011-09-08 09:10  kenter  阅读(683)  评论(0编辑  收藏  举报