Dmi*_*iyd 3 c# events delegates
我从C#简单的书中看到了这个例子(http://www.albahari.com/nutshell/ch04.aspx)
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 Stock
{
string symbol;
decimal price;
public Stock (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;
OnPriceChanged (new PriceChangedEventArgs (price, value));
price = value;
}
}
}
class Test
{
static void Main()
{
Stock stock = new Stock ("THPW");
stock.Price = 27.10M;
// register with the PriceChanged event
stock.PriceChanged += stock_PriceChanged;
stock.Price = 31.59M;
}
static void stock_PriceChanged (object sender, PriceChangedEventArgs e)
{
if ((e.NewPrice - e.LastPrice) / e.LastPrice > 0.1M)
Console.WriteLine ("Alert, 10% stock price increase!");
}
}
Run Code Online (Sandbox Code Playgroud)
我不明白,为什么使用这个惯例...
****protected virtual void OnPriceChanged (PriceChangedEventArgs e)
{
if (PriceChanged != null) PriceChanged (this, e);
}****
Run Code Online (Sandbox Code Playgroud)
为什么我需要这种方法,为什么我要给它"this"参数?!?不能直接用测试类中的方法PriceChanged附加该类中的事件并跳过该方法吗?!?
您需要进行空检查,因为在某人订阅之前,事件将为null.如果直接引发它并且它为null,则会抛出异常.
此方法用于引发事件,而不是订阅它.您可以轻松地从其他课程订阅该活动:
yourObject.PriceChanged += someMethodWithTheAppropriateSignature;
Run Code Online (Sandbox Code Playgroud)
但是,当您希望事件"触发"时,该类需要引发事件."this"参数提供了sender参数EventHandler<T>.按照惯例,用于事件的委托有两个参数,第一个是object sender,应该是引发事件的对象.第二个是EventArgs或它的子类EventArgs,它提供特定于该事件的信息.该方法用于正确检查null并使用适当的信息引发事件.
在这种情况下,您的事件被声明为:
public event EventHandler<PriceChangedEventArgs> PriceChanged;
Run Code Online (Sandbox Code Playgroud)
EventHandler<PriceChangedEventArgs> 是一个代表,其签名为:
public delegate void EventHandler<T>(object sender, T args) where T : EventArgs
Run Code Online (Sandbox Code Playgroud)
这意味着必须使用两个参数引发事件 - 对象(发件人或"this")和实例PriceChangedEventArgs.
话虽这么说,这个惯例实际上并不是提出这一事件的"最佳"方式.使用它实际上会更好:
protected virtual void OnPriceChanged (PriceChangedEventArgs e)
{
var eventHandler = this.PriceChanged;
if (eventHandler != null)
eventHandler(this, e);
}
Run Code Online (Sandbox Code Playgroud)
这可以在多线程场景中保护您,因为如果您有多个线程在运行,单个订阅可能实际上取消订阅您的空检查和加注.