1.事件含义
事件 .NET最常用的OOP技术
订阅(subscribe)一个事件:提供代码,事件发生时执行这些代码(事件处理程序)。
单个事件可供多个处理程序订阅。
菜鸟教程之事件event
2.处理事件
class Program
{
//事件
static int counter = 0;
static string displayString =
"This string will apper one letter at a time.";
static void Main(string[] args)
{
Timer myTimer = new Timer(100);
//ElapsedEventHandler elapsedEventHandler = new ElapsedEventHandler(WriteChar);
myTimer.Elapsed += new ElapsedEventHandler(WriteChar);
myTimer.Start();
System.Threading.Thread.Sleep(200);
Console.ReadKey();
}
private static void WriteChar(object source, ElapsedEventArgs e)
{
Console.Write(displayString[counter++ % displayString.Length]);
}
}
代码分析
3.定义事件
CH13Ex02
Program.cs
class Program
{
static void Main(string[] args)
{
Connection myConnection = new Connection();
Display myDisplay = new Display();
myConnection.MessageArrived +=
new MessageHandler(myDisplay.DisplayMessage);//订阅myDisplay.DisplayMessage
myConnection.Connect();
System.Threading.Thread.Sleep(200);
Console.ReadKey();
}
}
Connection.cs
//委托,可以把Connection对象收到的即时消息发送给Display对象。
public delegate void MessageHandler(string messageText);
class Connection
{
//命名事件,使用event关键字
//必须指定使用的委托类型
public event MessageHandler MessageArrived;
private Timer pollTimer;
public Connection()
{
//注册Elapsed事件的一个事件处理程序
pollTimer = new Timer(100);
pollTimer.Elapsed += new ElapsedEventHandler(CheckForMessage);
}
public void Connect() => pollTimer.Start();
public void Disconnect() => pollTimer.Stop();
private static Random random = new Random();
private void CheckForMessage(object sender, ElapsedEventArgs e)
{
WriteLine("Checking for new message.");
if((random.Next(9) == 0) && (MessageArrived != null))
{
MessageArrived("Hello Mami!");
}
}
}
Display.cs
class Display
{
public void DisplayMessage(string message)
=> WriteLine($"Message arrived: {message}");
}
1.多用途的事件处理程序
常见两类参数
object source
——引发事件的对象的应用
ElapsedEventArgs
——由事件传送的参数
使用object类型
的原因是:常常为几个不同对象引发几个相同事件使用同一个事件处理程序。
pollTimer.Elapsed += new ElapsedEventHandler(CheckForMessage);
pollTimer对象名称 Elapsed事件名称 +=订阅 委托名称 事件处理程序
//该方法更加通用
//使用as关键字,避免异常,检查null值
public void DisplayMessage(object source, EventArgs e)
{
WriteLine($"Message arrived from: {(source as Connection).Name}");
WriteLine($"Message Text: {(e as MessageArrivedEventArgs).Message}");
}
2.EventHandler
和泛型EventHandler<T>类型
简化了代码。
一般来说,在定义事件时,最好使用这些委托类型。注意,如果事件不需要事件实参数据,仍然可以使用EventHandler委托类型,只不过要传递EventArgs.Empty作为实参值。
3.返回值和事件处理程序
都是用void
使用其他返回值会出下问题,因为引发给定的事件可能会调用多个事件处理程序。入果这些处理程序都返回一个值,那么不知道该使用哪个返回值
解决:只允许访问由事件处理程序最后返回的那个值,也就是最后一个订阅该事件的处理程序返回的值。
最好使用void
类型的事件处理程序,且避免使用out参数,参数返回的值的源头不清楚
4.匿名方法
anonymous method 匿名方法
纯粹是为用作委托目的而创建的。
connection.MessageArrived +=
delegate(Connection source, MessageArrivedEventArgs e)
{
WriteLine($"Message arrived from: {(source as Connection).Name}");
WriteLine($"Message Text: {(e as MessageArrivedEventArgs).Message}\n");
};
运行时发生错误,还未解决
**注意:**如果外部变量占用大量内存,或者使用的资源在其他方面是比较昂贵的,就可能导致内存或性能问题