目录
-
事件概念(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>的委托函数都是没有返回值的。