1 using System; 2 3 namespace ConsoleApp1 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 Stock stock = new Stock("cmp"); 10 stock.Price = 27.10M; 11 stock.PriceChanged += stock_PriceChanged; 12 stock.Price = 31.59M; 13 } 14 15 static void stock_PriceChanged(object sender, PriceChangedEventArgs e) 16 { 17 if ((e.NewPrice - e.LastPrice / e.LastPrice) > 0.1M) 18 { 19 Console.WriteLine("Alert, 10% stock price increse! "); 20 } 21 } 22 } 23 /** 24 * .NET Framework 为 事件编程定义了一个标准模式,它的目的就是保持框架和用户代码的一致性。 25 * 标准事件模式的核心是System.EventArgs类,一个预定义的没有成员(但是有一个静态的Empty属性)的类。EventArgs 26 * 是为事件传递信息的基类。在Stock示例中,我们可以继承EventArgs以便在PriceChanged事件触发时 27 * 传递新的和旧的Price值: 28 */ 29 public class PriceChangedEventArgs : System.EventArgs 30 { 31 public readonly decimal LastPrice; 32 public readonly decimal NewPrice; 33 34 public PriceChangedEventArgs(decimal lastPrice, decimal newPrice) 35 { 36 LastPrice = lastPrice; 37 NewPrice = newPrice; 38 } 39 } 40 41 /** 42 * EventArgs子类就位后,下一步就是选择或者定义事件的委托了。这一步需要遵循三条规则: 43 * 1. 委托必须以void作为返回值。 44 * 2. 委托必须接受两个参数,第一个参数是object类型,第二个参数则是EventArgs的子类。 45 * 第一个参数表明了事件的广播者,第二个参数则包含了需要传递的额外信息。 46 * 3. 委托的名称必须以EventHandler结尾。框架定义了一个名为 System.EventHandler<>的泛型委托,该委托满足以上提到 47 * 的三个条件: 48 */ 49 50 51 //出于历史原因,框架中的大部分事件使用委托是这样定义的。 52 // public delegate void PriceChangedHandler(object sender, PriceChangedEvetArgs e); 53 54 public class Stock 55 { 56 string symbol; 57 decimal price; 58 public Stock(string symbol) 59 { 60 this.symbol = symbol; 61 } 62 //定义型泛型委托类型的事件,这里使用泛行的EventHander委托: 63 public event EventHandler<PriceChangedEventArgs> PriceChanged; 64 //编写一个protected虚方法来触发事件。方法名必须和事件名称一致以On作为前缀,并接收唯一的EventArgs参数: 65 protected virtual void OnPriceChanged(PriceChangedEventArgs e) 66 { 67 PriceChanged?.Invoke(this, e); 68 } 69 70 public decimal Price 71 { 72 get { return price; } 73 set 74 { 75 if (price == value) return; 76 77 decimal oldPrice = price; 78 price = value; 79 80 OnPriceChanged(new PriceChangedEventArgs(oldPrice, price)); 81 } 82 } 83 } 84 85 86 /** 87 * 如果事件不需要传递额外的信息,则可以使用预定义的非泛型委托EventHandler。 88 * 本例中,我们重写Stock类,当Price属性发生变化时, 89 * 触发PriceChanged事件,事件除了传达已发生的消息之外没有必须包含的信息。 90 * 为了避免创建非必要的EventArgs实例,我们使用 了EventArgs.Emtpy属性: 91 */ 92 93 public class Stock_Empty 94 { 95 string symbol; 96 decimal price; 97 public Stock_Empty(string symbol) { this.symbol = symbol; } 98 99 public event EventHandler PriceChanged; 100 protected virtual void OnPriceChanged(EventArgs e) 101 { 102 PriceChanged?.Invoke(this, e); 103 } 104 public decimal Price 105 { 106 get { return price; } 107 set 108 { 109 if (price == value) return; 110 111 price = value; 112 OnPriceChanged(EventArgs.Empty); 113 } 114 } 115 } 116 117 }View Code
参考:约瑟夫·阿坝哈瑞(Joseph Albahari); 本·阿坝哈瑞(Ben Albahari). C# 7.0核心技术指南(原书第7版) (O’Reilly精品图书系列) (Kindle位置3328). 北京华章图文信息有限公司. Kindle 版本.