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(); // 防止控制台自动关闭
}
}
}