在面試的時候經常會被問到,委託和事件的聯絡和區別?之前也一直沒有徹底搞明白,下面就來總結一下。
從一個有趣的需求入手。有三個角色,貓,老鼠和主人,當貓叫的時候,老鼠開始逃跑,主人則從睡夢中驚醒。
使用事件實現
如下代碼:
1 namespace ConsoleApplication4 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 Cat cat = new Cat("貓"); 8 Mouse mouse1 = new Mouse("老鼠", cat); 9 Master master = new Master("張三", cat);10 //貓叫,通知所有訂閱者11 cat.CatCry();12 13 Console.ReadKey();14 }15 }16 17 #region 貓18 public class Cat19 {20 private string name;21 22 //聲明事件23 public event EventHandler<CatCryEventArgs> CatCryEvent;24 25 public Cat(string name)26 {27 this.name = name;28 }29 30 public void CatCry()31 {32 //聲明事件參數33 CatCryEventArgs args = new CatCryEventArgs(name);34 Console.WriteLine(args);35 36 //觸發事件37 CatCryEvent(this, args);38 }39 }40 41 /// <summary>42 /// 事件參數43 /// </summary>44 public class CatCryEventArgs : EventArgs45 {46 private string catName;47 48 public CatCryEventArgs(string catName)49 : base()50 {51 this.catName = catName;52 }53 54 public override string ToString()55 {56 return string.Format("{0}叫了", catName);57 }58 }59 #endregion60 61 #region 老鼠62 public class Mouse63 {64 private string name;65 public Mouse(string name, Cat cat)66 {67 this.name = name;68 cat.CatCryEvent += CatCryEventHandler;//本質上就是往委託鏈中添加一個方法69 }70 71 //事件處理常式72 private void CatCryEventHandler(object sender, CatCryEventArgs e)73 {74 Console.WriteLine("{0}逃走了:我勒個去,趕緊跑啊!", name);75 }76 }77 #endregion78 79 #region 主人80 public class Master81 {82 private string name;83 public Master(string name, Cat cat)84 {85 this.name = name;86 cat.CatCryEvent += CatCryEventHandler;//本質上就是往委託鏈中添加一個方法87 }88 89 //事件處理常式90 private void CatCryEventHandler(object sender, CatCryEventArgs e)91 {92 Console.WriteLine("{0}醒了:我勒個去,叫個鎚子!", name);93 }94 }95 #endregion96 97 }
通過demo可以總結:
1,定義和使用事件的流程,如:
2,定義事件參數要繼承EventArgs,定義事件使用public event EventHandler<CatCryEventArgs> CatCryEvent;
3,事件使用了觀察者模式,有發布,訂閱和通知,至於怎麼實現的,本質是什麼下面會總結到。
使用委託實現
1 namespace ConsoleApplication5 2 { 3 //聲明委託 4 public delegate void Del1(); 5 6 class Program 7 { 8 static void Main(string[] args) 9 {10 //建立委託鏈(鏈式委託)11 Del1 del1 = () => Console.WriteLine("貓叫了");12 del1 += () => Console.WriteLine("老鼠逃走了:我勒個去,趕緊跑啊!");13 del1 += () => Console.WriteLine("主人醒了:我勒個去,叫個鎚子!");14 15 //調用委託16 del1();17 18 Console.ReadKey();19 }20 21 }22 }
可以看出,其實就是一個鏈式委託的調用。向鏈式委託添加了三個方法,調用的時候依次執行。
事件和委託
為了弄清徹底弄清事件和委託的關係,我們查看下EventHandler的原始碼,如。
看到的紅色標記了嗎?所以,事件是基於委託實現的。總結一下:
聯絡:
1,事件是基於委託實現的,可以通俗地理解為:事件是一種特殊的委託,特殊的地方在於它定義的是一個有兩個參數(事件來源和事件參數)沒有傳回值的委託。
2,當事件的訂閱者訂閱事件時,本質上是將事件的處理方法加入到委託鏈中,當事件觸發時,委託鏈中的所有事件處理方法都會被調用。
區別:
委託本質是一種自訂類型(class),而事件本質是一個特殊的委託執行個體(對象)。