C#委託和事件

委託app

委託與事件,常常拿來就用,每每忘記其實現原理,對其使用方式也愈來愈侷限。周家安老師在《C# 6.0 學習筆記》中對委託和事件的講解,深刻淺出,清晰明瞭,故特地摘抄一篇隨筆,勤看勤思。學習

首先,委託是一種形式上與方法簽名類似的類型。this

定義一個委託:spa

public delegate void DoSome(string msg);

 

使用關鍵字 delegate, 類型名稱爲 DoSome(string msg).code

 

 

建立一個DoSome(string msg)委託類型對象,並實例化。對象

 1 static void TestDo(string str)
 2 {
 3      // ToDo
 4 }
 5 
 6 
 7 DoSome d1 = new DoSome(TestDo);
 8 
 9 
10 // 或者
11 
12 DoSome  d2;
13 
14 d2 = TestDo;

 委託列表blog

 1 public delegate void DoSome(string msg);
 2 static void Main(string[] args)
 3 {
 4     DoSome d = new DoSome(TestDo);
 5     d("Hello");
 6     Console.WriteLine("--------------------------------------");
 7     d += new DoSome(Test1);
 8     d("123");
 9     Console.WriteLine("--------------------------------------");
10     d += TDo2;
11     d("world");
12     Console.WriteLine("--------------------------------------");
13     d -= TestDo;
14     d("nihao");
15 }
16 
17 static void TestDo(string str)
18 {
19     Console.WriteLine(str);
20 }
21 
22 static void Test1(string str)
23 {
24     Console.WriteLine("Test1 + " + str);
25 }
26 static void TDo2(string str)
27 {
28     Console.WriteLine("TDo2 + " + str);
29 }

輸出:接口

 

事件事件

 事件自身就是委託類型。get

 1     class MyApp
 2     {
 3         public delegate void SpaceKeyPressedEventHandler();
 4 
 5         // 聲明事件
 6         public event SpaceKeyPressedEventHandler SpaceKeyPressed;
 7 
 8         // 經過該方法引起事件
 9         protected virtual void OnSpaceKeyPressed()
10         {
11 
12             if (this.SpaceKeyPressed != null)
13             {
14                 // 將事件分發
15                 SpaceKeyPressed();
16             }
17         }
18 
19         // 啓動事件監聽的接口
20         public void StartRun()
21         {
22             // 監聽事件
23             while (true)
24             {
25                 ConsoleKeyInfo keyinfo = Console.ReadKey();
26                 if (keyinfo.Key == ConsoleKey.Spacebar)
27                 {
28                     // 引起事件
29                     OnSpaceKeyPressed();
30                 }
31 
32                 if (keyinfo.Key == ConsoleKey.Escape)
33                 {
34                     // 跳出循環
35                     break;
36                 }
37             }
38         }
39     }
40 
41     class Program
42     {
43        
44         static void Main(string[] args)
45         {
46             MyApp app = new MyApp();
47             // 訂閱事件,指定處理事件的方法
48             app.SpaceKeyPressed += app_SpaceKeyPressed;
49             app.SpaceKeyPressed += app_SecondEventHandler;
50 
51             // 啓動事件監聽
52             app.StartRun();
53         
54         }   
55 
56         // 事件處理1
57         private static void app_SpaceKeyPressed()
58         {
59             Console.WriteLine("{0} 按下空格鍵。", DateTime.Now.ToLongTimeString());
60         }
61         // 事件處理2
62         private static void app_SecondEventHandler()
63         {
64             Console.WriteLine("事件的第二個處理方法。");
65         }
66 
67     }

一般,做爲事件委託,有兩個參數,一個是Object類型,表示引起事件的對象,便是誰引起了事件的,多數狀況下在調用事件時是把類的當前實例引用(this)傳遞過去。另外一個參數是從System.EventArgs派省的類的實例。這是一個標準的事件處理程序的簽名,爲了規範事件的處理,.NET類庫已經定義好一個System.EventHandler委託,用於聲明事件。它的原型以下:

1 public delegate void EventHandler(object sender, EventArgs e);

 引起事件的對象實例將傳遞給sender參數,而與事件相關的數據則傳遞給e參數。若是不須要傳遞過多的數據,能夠經過System.EventArgs.Empty靜態成員返回一個空的EventArgs對象類傳遞。

可是,因爲不一樣的事件要傳遞的參數不一樣,更多時候是從EventArgs類派生的子類的實例,顯然一個EventHandler委託是不能知足各類狀況的。若是針對不一樣的事件也頂一個一個對應的委託,水量一旦多起來,既混亂,也很差管理。爲了解決這個問題,.NET類庫又提供了一個帶有泛型參數的事件處理委託。原型以下:

1 public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);

TEventArgs 是一個泛型參數,應該是System.EventArgs類或者System.EventArgs類的派生類型。

泛型參數的事件,實例:

 1     // EventArgs 派生類
 2     // 建立泛型參數  KeyPressedEventArgs 類
 3     public class KeyPressedEventArgs : EventArgs
 4     {
 5         public ConsoleKey pressedKey { get; private set; }
 6         public KeyPressedEventArgs(ConsoleKey key)
 7         {
 8             pressedKey = key;
 9         }
10     }
11 
12     public class MyApp
13     {
14         // 捕捉按鍵的事件 聲明一個泛型參數KeyPressedEventArgs類型的
15         public event EventHandler<KeyPressedEventArgs> KeyPressed;
16 
17         // 經過該方法引起事件
18         protected virtual void OnKeyPressed(KeyPressedEventArgs e)
19         {
20             if (this.KeyPressed != null )
21             {
22                 this.KeyPressed(this, e);
23             }
24         }
25 
26         // 事件監聽端口啓動
27         public void Start()
28         {
29             while (true)
30             {
31                 ConsoleKeyInfo keyInfo = Console.ReadKey();
32                 // 若是按下了ESC鍵,則退出循環
33                 if (keyInfo.Key == ConsoleKey.Escape)
34                 {
35                     break;
36                 }
37                 // 引起事件
38                 OnKeyPressed(new KeyPressedEventArgs(keyInfo.Key));
39             }
40         }
41     }
42 
43 
44     class Program
45     {
46        
47         static void Main(string[] args)
48         {
49             
50             MyApp app = new MyApp();
51             // 訂閱事件,指定處理事件的方法
52             app.KeyPressed += app_KeyPressed;
53             // 啓動事件監聽
54             app.Start();
55         }   
56 
57         // 事件處理
58         private static void app_KeyPressed(Object sender, KeyPressedEventArgs e)
59         {
60             Console.WriteLine("已按下 {0} 鍵", e.pressedKey.ToString());
61         }
62         
63     }
相關文章
相關標籤/搜索