zoukankan      html  css  js  c++  java
  • 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<TResult>;有参数:Func<T,TResult>,T代表传入参数类型,TResult代表返回参数类型,当然可以有多个参数T1、T2、T3…
        延伸3.Action<T>的用法与Func几乎一样,调用方法也类似,两者都支持Lambda表达式。
        延伸4:Func与Action的区别
        Func与Action作用几乎一样。只是Func<Result>有返回类型;Action<T>只有参数类型,不能传返回类型。所以Action<T>的委托函数都是没有返回值的。
  • 相关阅读:
    (转)C# 泛型委托 Action<>和Func<>
    (转)ASP.NET Core 中间件与筛选器
    react中将svg做成icon组件在其他模块调用
    react简单的tab切换 (styled-components)
    计算购物车金额总和( jquery )
    js分享功能(微信,QQ,微博,空间,豆瓣等)
    AJAX入门介绍
    作为前端,你不得不知道的搜索引擎优化
    微信小程序实现图片双滑缩放大小
    swiper实现一个好看的轮播图
  • 原文地址:https://www.cnblogs.com/wecc/p/11252430.html
Copyright © 2011-2022 走看看