C#事件与委托是C#中一种重要的机制,它可以让程序员在不同的类之间进行消息传递,从而实现解耦。事件与委托是C#中一种强大的机制,它可以帮助我们实现面向对象的设计模式。
事件是一种特殊的函数,它可以在特定条件下被调用。当特定条件满足时,事件就会发生。例如,当用户单击某个按钮时,就会发生单击事件。
委托是一种特殊的数据类型,它可以存储方法的引用。当我们需要在不同的类之间进行方法调用时,就可以使用委托来存储方法的引用并把这个引用传递到其它类中去。
C#中的事件与委托是相关联的:当特定条件满足时(例如单击某个按钮时),就会发生一个事件;而这个事件激发时把存储在委托中的方法引用也传递到具体处理该事情的代码中去。
public delegate void MyDelegate(string message); // 声明一个委托 public event MyDelegate MyEvent; // 声明一个事件 public void DoSomething() // 方法 { if (MyEvent != null) // 检测MyEvent是否有处理函数 { MyEvent("Hello World!"); // 触发MyEvent, 并把"Hello World!"作为参数传递出去. } }
事件系统是软件系统的核心部分。例如,按钮可以触发点击事件。批处理作业可以生成作业完成事件。学生系统将使用注册事件。
广播者是包含委托字段的类型。
广播者决定何时广播,通过调用委托。
订阅者是方法目标收件人。
事件是一个C#语言功能,正式化这种模式。
要声明事件,请将事件关键字放在代理成员的前面:
// a delegate public delegate void ValueChangedHandler (decimal oldPrice, decimal newPrice); public class Broadcaster { // Event declaration public event ValueChangedHandler PriceChanged; }
Broadcaster
类型中的代码具有对 PriceChanged
的完全访问权限,可以将其视为代理。
Broadcaster
外部的代码只能对PriceChanged
事件执行+ =和 - =操作。
.NET Framework定义了用于写入事件的标准模式。
System.EventArgs
是一个没有成员的预定义的Framework类。
EventArgs
是一个承载事件信息的基类。
以下代码将 EventArgs
子类化,以启动PriceChanged
事件时存储旧价格和新价格:
public class PriceChangedEventArgs : System.EventArgs { public readonly decimal LastPrice; public readonly decimal NewPrice; public PriceChangedEventArgs (decimal lastPrice, decimal newPrice) { LastPrice = lastPrice; NewPrice = newPrice; } }
EventArgs
子类根据其包含的信息命名。
它通常将数据作为属性或作为只读字段公开。
创建 EventArgs
子类之后,下一步是为事件定义一个委托,它是事件处理程序委托。
事件处理程序委托必须有一个void返回类型。
事件处理程序委托必须接受两个参数:第一个是类型对象,第二个是EventArgs的子类。
第一个参数指示事件广播者,第二个参数包含要传达的额外信息。
事件处理程序委托的名称必须以 EventHandler
结尾。
框架定义了一个称为 System.EventHandler<>
的通用委托,它满足这些规则:
public
delegate
void
EventHandler<TEventArgs> (object source, TEventArgs e)
where TEventArgs : EventArgs;
以下代码定义了我们的值更改事件的委托。
public delegate void ValueChangedHandler (object sender, PriceChangedEventArgs e);
下一步是定义所选委托类型的事件。
在这里,我们使用通用 EventHandler
委托:
public class Product { public event EventHandler<PriceChangedEventArgs> PriceChanged; }
最后,该模式需要您编写一个受保护的虚拟方法来触发事件。
该名称必须与事件的名称匹配,前缀为单词On,并接受单个EventArgs参数:
public class Product { ... public event EventHandler<PriceChangedEventArgs> PriceChanged; protected virtual void OnPriceChanged (PriceChangedEventArgs e) { if (PriceChanged != null) PriceChanged (this, e); } }
这里是完整的例子:
using System;
public class PriceChangedEventArgs : EventArgs {
public readonly decimal LastPrice;
public readonly decimal NewPrice;
public PriceChangedEventArgs (decimal lastPrice, decimal newPrice) {
LastPrice = lastPrice; NewPrice = newPrice;
}
}
public class Product {
string symbol;
decimal price;
public Product (string symbol) {
this.symbol = symbol;
}
public event EventHandler<PriceChangedEventArgs> PriceChanged;
protected virtual void OnPriceChanged (PriceChangedEventArgs e) {
if (PriceChanged != null) {
PriceChanged (this, e);
}
}
public decimal Price {
get {
return price;
}
set {
if (price == value) return;
decimal oldPrice = price;
price = value;
OnPriceChanged (new PriceChangedEventArgs (oldPrice, price));
}
}
}
class Test {
static void Main() {
Product stock = new Product ("THPW");
stock.Price = 2.10M;
// Register with the PriceChanged event
stock.PriceChanged += stock_PriceChanged;
stock.Price = 3.9M;
}
static void stock_PriceChanged (object sender, PriceChangedEventArgs e) {
if (e.NewPrice - e.LastPrice > 0){
Console.WriteLine ("Alert!");
}
}
}
事件的访问器是其 + =
和 - =
函数。
默认情况下,访问器由编译器隐式实现。
像方法一样,事件可以是虚拟的,重写的,抽象的或密封的。
事件也可以是静态的:
public class Product {
public static event EventHandler<EventArgs> StaticEvent;
public virtual event EventHandler<EventArgs> VirtualEvent;
}
C#抽象类抽象类是表示抽象概念的特殊类。例如,Integer是一个具体而Number是抽象的。形状是抽象的,而圆形是具体的。一个声明为...
C#继承的成员隐藏继承的成员基类和子类可以定义相同的成员。例如:public class A {public int Counter = 1; } public class B ...
C#GetType和typeofC#中的所有类型都在运行时由System.Type的实例表示。有两种基本方法来获取System.Type对象:在实例上调用Get...