1、事件
事件是一种专门的代表类型,主要用于消息或通知传递。事件只能从它们发布的类型调用,通常基于EventHandler
委托,其中对象代表事件的发送方,System.EventArgs
派生类保存有关事件的数据。实现事件和回调方法都是基于委托(delegate)。
2、事件的声明
相关文档:C# 委托(delegate)
声明事件需要先声明该事件的委托型类,通过声明的委托类型和event
关键字来声明事件。
例如,
public delegate void ClickEventHandler(string args); // 基于上面的委托定义事件 public event ClickEventHandler ClickEvent;
以上代码简单实现了事件ClickEvent
的定义,该事件在声明的时会调用委托。下面看一下通过“订阅者”和“发布者”类实现的完整示例:
例如,
using System; namespace SimpleEvent { using System; /***********发布器类***********/ public class EventDemo { private string message; public delegate void PrintEventHandler(); public event PrintEventHandler PrintEvent; protected virtual void OnPrinted() { if ( PrintEvent != null ) { PrintEvent(); /* 事件被触发 */ }else { Console.WriteLine( "事件没被触发" ); Console.ReadKey(); /* 回车继续 */ } } public EventDemo() { PrintMessage("cjavapy"); } public void PrintMessage( string s ) { message=s; OnPrinted(); } } /***********订阅器类***********/ public class SubscribEvent { public void Print() { Console.WriteLine( "触发事件" ); Console.ReadKey(); /* 回车继续 */ } } /***********触发***********/ public class MainClass { public static void Main() { EventDemo e = new EventDemo(); /* 实例化对象,第一次没有触发事件 */ SubscribEvent s = new SubscribEvent(); /* 实例化对象 */ e.PrintEvent += new EventDemo.PrintEventHandler(s.Print); /* 注册 */ e.PrintMessage("C#"); e.PrintMessage("Java"); } } }
上面示例的事件没有参数,下面看一下委托事件带有参数的情况:
例如,
using System; namespace SimpleEvent { using System; /***********发布器类***********/ public class EventDemo { private string message; public delegate void PrintEventHandler(string args); public event PrintEventHandler PrintEvent; protected virtual void OnPrinted(string s) { if ( PrintEvent != null ) { PrintEvent(s); /* 事件被触发 */ }else { Console.WriteLine( "事件没被触发" ); Console.ReadKey(); /* 回车继续 */ } } public EventDemo() { PrintMessage("cjavapy"); } public void PrintMessage( string s ) { message=s; OnPrinted(s); } } /***********订阅器类***********/ public class SubscribEvent { public void Print(string s) { Console.WriteLine( "触发事件" ); Console.WriteLine( s ); Console.ReadKey(); /* 回车继续 */ } } /***********触发***********/ public class MainClass { public static void Main() { EventDemo e = new EventDemo(); /* 实例化对象,第一次没有触发事件 */ SubscribEvent s = new SubscribEvent(); /* 实例化对象 */ e.PrintEvent += new EventDemo.PrintEventHandler(s.Print); /* 注册 */ e.PrintMessage("C#"); e.PrintMessage("Java"); } } }
3、使用内置委托(推荐写法)
从 .NET 2.0 开始,推荐使用泛型委托 EventHandler
或 EventHandler<T>
。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication { public class Publisher { // 定义一个事件,使用内置泛型委托 EventHandler<T> public event EventHandler<EventArgs> OnPublish; // 模拟执行某个操作,然后触发事件 public void DoWork() { Console.WriteLine("Working..."); // 触发事件,通知订阅者 OnPublish?.Invoke(this, EventArgs.Empty); } } public class Program { public static void Main(string[] args) { // 创建发布者实例 Publisher p = new Publisher(); // 订阅事件(匿名方法) p.OnPublish += (sender, e) => Console.WriteLine("事件触发!"); // 执行操作,触发事件 p.DoWork(); Console.ReadLine(); // 防止控制台自动关闭 } } }