云在青天部落阁

独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!
扩大
缩小

C#的事件与委托

目录

  • 事件概念:

    事件概念(Event):所谓的事件是指用户的操作,或者是一些提示信息等等。应用程序需要在事件发生时响应事件。C#中使用事件机制实现线程间的通信。

  • 通过事件使用委托相关概念:

    事件在类中声明且生成,且通过使用同一个类或其他类中的委托与事件处理程序关联。包含事件的类用于发布事件。这被称为 发布器(publisher) 类。其他接受该事件的类被称为 订阅器(subscriber) 类。事件使用 发布-订阅(publisher-subscriber) 模型。
    发布器(publisher) 是一个包含事件和委托定义的对象。事件和委托之间的联系也定义在这个对象中。发布器(publisher)类的对象调用这个事件,并通知其他的对象。
    订阅器(subscriber) 是一个接受事件并提供事件处理程序的对象。在发布器(publisher)类中的委托调用订阅器(subscriber)类中的方法(事件处理程序)。

  • [声明事件:]

    在类的内部声明事件,首先必须声明该事件的委托类型,e.gpublic delegate void BoilerLogHandler(string status);然后,声明事件本身,使用 event 关键字,
    // 基于上面的委托定义事件
    public event BoilerLogHandler BoilerEventLog;
    上面的代码定义了一个名为 BoilerLogHandler 的委托和一个名为 BoilerEventLog 的事件,该事件在生成的时候会调用委托,委托调用订阅器里面的方法(事件处理程序处理事件)。

  • [插入一个小片段----Virtual(虚方法):]

    virtual关键字用于在基类中修饰方法。virtual的使用会有两种情况:
    情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法。那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法。
    情况2:在基类中定义了virtual方法,然后在派生类中使用override重写该方法。那么在对派生类实例的调用中,该虚方法使用的是派生重写的方法。
    代码示例一:
    using System;
    namespace SimpleEvent
    {
    /发布器类/
    public class EventTest
    {
    private int value;

    public delegate void NumManipulationHandler();

    public event NumManipulationHandler ChangeNum;
    protected virtual void OnNumChanged()
    {
    if ( ChangeNum != null )
    {
    ChangeNum(); /* 事件被触发 /
    }else {
    Console.WriteLine( "event not fire" );
    Console.ReadKey(); /
    回车继续 */
    }
    }

    public EventTest()
    {
    int n = 5;
    SetValue( n );
    }

    public void SetValue( int n )
    {
    if ( value != n )
    {
    value = n;
    OnNumChanged();
    }
    }
    }

    /订阅器类/

    public class subscribEvent
    {
    public void printf()
    {
    Console.WriteLine( "event fire" );
    Console.ReadKey(); /* 回车继续 */
    }
    }

    /触发/
    public class MainClass
    {
    public static void Main()
    {
    EventTest e = new EventTest(); /* 实例化对象,第一次没有触发事件 /
    subscribEvent v = new subscribEvent(); /
    实例化对象 /
    e.ChangeNum += new EventTest.NumManipulationHandler( v.printf ); /
    注册 */
    e.SetValue( 7 );
    e.SetValue( 11 );
    }
    }}

  • [代码解析与延伸:]

    e.g:ChangeNum += new EventTest.NumManipulationHandler( v.printf ); /* 注册 */
    解析1:-->这里就是简单的给事件赋值操作而已;new EventTest.NumManipulationHandler( v.printf )-->事件的处理程序通过委托去调用;老的C#版本中会这样去调用,在如今的C#版本中,使用的是直接把事件处理方法赋值给事件--e.g ChangeNum = v.printf ;此外,还有一个点要注意,把方法传给委托时,方法的参数列表和返回值类型和委托的一致才可以。
    e.g:public event NumManipulationHandler ChangeNum;
    延伸1:event NumManipulationHandler可理解为一种类型,在C#新发布的版本中,可以用Action来代替传统的委托声明方式,e.g:public delegate int NumManipulationHandler();等效于public Action ChangeNum;
    延伸2.以前为了能调用一个方法,必须定义一个相应的delegate,后来便有了通用委托Func<>,方便多了。没有参数: Func;有参数:Func<T,TResult>,T代表传入参数类型,TResult代表返回参数类型,当然可以有多个参数T1、T2、T3…
    延伸3.Action的用法与Func几乎一样,调用方法也类似,两者都支持Lambda表达式。
    延伸4:Func与Action的区别
    Func与Action作用几乎一样。只是Func有返回类型;Action只有参数类型,不能传返回类型。所以Action的委托函数都是没有返回值的。

posted on 2019-07-26 19:43  NoMatterTryAgain  阅读(314)  评论(0)    收藏  举报

导航