Never give up - LEO

人 只有在合适的地方 才能体现出最大的价值
  博客园  :: 首页  :: 联系 :: 订阅 订阅  :: 管理

C#委托和事件

Posted on 2007-01-12 11:21  lizhiwen  阅读(570)  评论(0)    收藏  举报

一、C#委托。Delegate

委托是一种特殊的类型,可以看成是一种新的对象类型,用于方法对方法的调用。

 

委托的声明

public delegate void MyDelegate(string str);

访问修饰字 delegate 返回类型 委托名称 [参数列表]

委托调用:[名称限定.]委托实例名([参数列表]

 

l         委托相当于C++中的函数指针,但它是类型安全的。

l         委托是从System.Delegate派生,但不能象定义常规类型一样直接从System.Delegate派生,对委托的声明只能通过上面的声明格式进行定义。关键字delegate通知编译器这是一个委托类型,从而在编译的时候对该类进行封装,对这一过程C#定义了专门的语法来处理这一过程。

l         不能从一个委托类型进行派生,因为它也是默认sealed

l         委托即可以对静态方法进行调用也可以对实例方法进行调用,甚至另一个委托。

l         每个委托类型包含一个自己的调用列表,当组合一个委托或从一个委托中删除一个委托时都将产生个新的调用列表。

l         单点委托:委托一旦被实例化,将始终引用同一目标对象和方法;

l         多点委托Mutlicast delegate:可以将一个委托实例与多个方法关联,支持运算符=,+, -, +=, -=,调用委托实例时按顺序调用.在使用多点委托时尽量不要使用有返回值的方法。删除的时候因该从最后一个开始。

l         两个不同类型的委托即使它们有相同的签名和返回值,但还是两个不同类型的委托。但其实在使用中可看作是相同的。

 

例子:

public class PrintStr

{              

    public void CallPrint(string input)

        {

            Console.WriteLine(input);

        }

}

 

public delegate void PrintHandler(string str);    // 声明委托类型

 

public class MyClass

{

    public static void Main()

         {

            PrintStr myPrinter = new PrintStr();

            PrintHandler myHandler = null;

            myHandler += new PrintHandler(myPrinter.CallPrint); // 将委托链接到方法,来实例化委托

            if(myHandler!=null)

                   myHandler("Hello World!");    // 调用委托,相当于匿名调用委托所链接的方法

            Console.Read();

         }

}

 

委托的比较

 

C#中对委托定义了两个操作符 == !=

在以下情况下两个委托是相等的:

l         当两个委托都同时为null的时候

l         当两个委托都不为null,下列情况下是相等的。

l         当两个委托的各自的调用列表只含有一个入口点的时候

a.在下列情况下是相等的

   (1) 调用同一对象的同一静态方法

   (2) 调用同一对象的同一实例方法

b.当两个委托具有多个入口点时

   在下列情况下是相等的

   (1)只有当它们调用列表中的调用的方法按顺序都一一对应相同的对象及对象的同一方法的时候

如上所述的两个不同类型的委托但是它们具有相同的签名和返回值时,只要满足上述条件的,即使它们类型不同,但比较的结果也是相同的。

 

委托的异常处理

l         当调用该委托的方法中发生了异常时,首先在调用该委托的方法中搜寻catch语句块。如果没有,则去该委托调用的方法中去寻找有没有catch语句块,这和调用方法发生异常的处理是一样的。

l         当调用一个为null的委托即委托中列表中不存在调用方法时,将发生NullRefrenceException

 

委托的注意点:

l         当一个委托有多个入口点的时候,调用委托将依该委托的调用列表中的方法的顺序依次调用.这些方法共享一个参数集合,所以当委托有返回值的时候调用完这个委托后的返回值是最后一个方法的返回值或是有out参数.如果该委托的参数为ref(引用类型),那么在招待第一个方法的时候如果对这个参数的值有所改变,那么这个改变将会影响到后面的方法调用.

 

 

二、C#事件。Event

事件实质上是一个委托实例,是委托的一种特殊形式。

 

sender(触发事件的对象)和receiver(捕获事件并作出响应的对象)之间使用委托作为媒介,在发布事件的类中定义用委托声明的事件,在事件接收方(用户类)中定义响应事件的事件处理方法;采用“发布/订阅”模式,发送方类发布一组事件供其他类订阅,当发布类产生事件时,所有订阅对象都会得到通知。

 

事件的声明:<access modifier> event <delegate type> EventName

 

为事件使用的委托类型进行声明时有更严格的规定:

l         事件的委托类型应采用两个参数;

l         两个参数分别是:指示事件源的“对象源”参数和封装事件的其他任何相关信息的“e”参数;

l         e”参数的类型应为EventArgs 类或派生自 EventArgs 类。

 

事件例子:

//自定义事件类

       public class PageBorwseButtonClickEventArgs : EventArgs

       {

             

              private int nPageIndex;  

              private int nPageSize;    

             

              public int PageIndex

              {

                     get

                     {

                            return this.nPageIndex;

                     }

              }

             

              public int PageSize

              {

                     get

                     {

                            return this.nPageSize;

                     }

              }

                           

              public PageBorwseButtonClickEventArgs(int pageIndex,int pageSize ) : base()

              {

                     this.nPageIndex = pageIndex;

                     this.nPageSize = pageSize;

              }

       }

       #endregion

 

       //自定义委托

       public delegate void PageBrowseEventHandler(object sender, PageBorwseButtonClickEventArgs e );

             

       public class PageBrowse : System.Web.UI.WebControls.WebControl, IPostBackEventHandler

       {

             

              private static readonly object EventPageBrowseClick = new object();

             

              // 事件绑定到委托

              public event PageBrowseEventHandler PageBrowseClick

              {

                     add

                     {

                            Events.AddHandler(EventPageBrowseClick, value );

                     }

                     remove

                     {

                            Events.RemoveHandler(EventPageBrowseClick, value );

                     }

              }

             

              protected void OnPageBrowseClick(PageBorwseButtonClickEventArgs e )

              {

                     PageBrowseEventHandler PageBrowseClick = (PageBrowseEventHandler)Events[EventPageBrowseClick];

                     if(PageBrowseClick != null )

                     {

                            PageBrowseClick(this, e );

                     }

              }

             

              public void RaisePostBackEvent(string eventArgument)

              {

                     PageBorwseButtonClickEventArgs e = new PageBorwseButtonClickEventArgs(nNowPageIndex, nNowPageSize );

                     //引发事件

                     this.OnPageBrowseClick(e );

              }

       }

 

委托和事件的使用可以参照:

http://blog.csdn.net/dongli1218/archive/2006/04/18/667336.aspx