1.事件模型建立在委托的基础上。
2,定义事件编译器会做三个动作,第一个构造具有委托类型的字段,事件发生时会通知这个列表中的委托。
第二个构造的是一个添加关注的方法+=。
第三个构造是一个注销事件关注的方法-=。
3,一个对象不再希望接收事件通知时应该注销对事件的关注,只要一个对象仍向事件登记了一个方法,这个对象不能垃圾回收,所以你的对象若实现了IDisposable的Dispose方法,应该注销对所有事件的关注。
4,-=,remove一个不存在的委托时,不会报错。
下面是一个定义事件的标准写法:引用http://blog.csdn.net/sun_dragon/article/details/8726681
1,定义一个类型来容纳所有应该发送给事件通知接收者的附加信息
2,定义事件成员
3,定义负责引发事件的方法来通知事件的登记对象
class PriceChangedEventArgs : EventArgs { public readonly decimal LastPrice; public readonly decimal NewPrice; public PriceChangedEventArgs(decimal lp, decimal np) { LastPrice = lp; NewPrice = np; } }
/// <summary> /// 扩展方法,用来封装这个线程的逻辑安全 /// </summary> public static class EventArgExtensions { public static void Raise<TEventArgs>(this TEventArgs e,object sender,ref EventHandler<TEventArgs> eventDelegate)where TEventArgs:EventArgs { //Interlocked需要4.5环境 //处于线程安全考虑,现在将委托字段的引用复制到一个临时字段中 EventHandler<TEventArgs> temp = Interlocked.CompareExchange(ref eventDelegate, null, null); if (temp != null) temp(sender, e); } }
class Stock//即是广播又是接收 { decimal price; //string symbol = "stock"; public event EventHandler<PriceChangedEventArgs> PriceChanged; public decimal Price { get { return price; } set { if (price != value) { OnPriceChanged(new PriceChangedEventArgs(price, value));//事件触发 } price = value; } } //简单写法,通常这个就够了 //protected virtual void OnPriceChanged(PriceChangedEventArgs e) //{ // if (PriceChanged != null) // PriceChanged(this, e); //} /// <summary> /// 线程安全写法,事件主要在单线程中使用,线程安全并不是一个问题,先记下有这个东西 /// 考虑这个线程竞态条件应该意识到一个方法可能在从事件的委托链中移除后得到调用 /// </summary> /// <param name="e"></param> protected virtual void OnPriceChanged(PriceChangedEventArgs e) { e.Raise(this,ref PriceChanged); } }
最后是调用
class EvenManage { static void priceChangeInMain(Object sender, PriceChangedEventArgs e) { System.Console.WriteLine(sender.ToString()); System.Console.WriteLine("last price" + e.LastPrice + "\nnew price" + e.NewPrice); } public static void text() { Stock s = new Stock(); s.Price = 100M;//这时没有调用priceChangeInMain,因为没有添加事件 s.PriceChanged += priceChangeInMain; s.Price = 200M;//添加完事件之后的触发调用了priceChangeInMain } }