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

  • 相关阅读:
    android的消息处理机制 Looper,Handler,Message
    AndroidManifest.xml 文件
    漫谈数据库索引 | 脚印 footprint(转载)
    Progress Indication while Uploading/Downloading Files using WCF(WCF制作带进度条的上传/下载)(转载)
    (转)ADO.net,Linq to SQL和Entity Framework性能实测分析
    Silverlight使用webClient上传下载
    RIA Services Staying Logged In (Ria Service持久登陆,sessioncookie,notcookie)
    OpenGL中的glLoadIdentity、glTranslatef、glRotatef原理
    Microsoft .NET 中的简化加密(转)
    Fluent API for .NET RIA Services Metadata(Reproduced)
  • 原文地址:https://www.cnblogs.com/kenter/p/2170521.html
Copyright © 2020-2023  润新知