本節對事件進行總結。 二、事件: 1、概念:Event:A member that enables an object or class to provide notifications;官方的解釋是這樣,就是說在C#中,事件是使 對象或者類具備通知能力的成員。比如說手機收到簡訊提醒我去開會,那麼手 ...
本節對事件進行總結。
二、事件:
1、概念:Event:A member that enables an object or class to provide notifications;官方的解釋是這樣,就是說在C#中,事件是使
對象或者類具備通知能力的成員。比如說手機收到簡訊提醒我去開會,那麼手機就充當了一個具備通知能力的成員。說白了,事件
的作用就是對象和類之間的信息傳遞的橋梁。
2、原理:源於發生-響應模型:
事件源(event source) + 事件本身(event) => 事件的訂閱者(event subscriber) + 事件處理器(event handler)
(另外還有事件的訂閱者和事件源之間的訂閱關係subscribe relationship)
還是以手機收到簡訊提醒我去開會為例,事件源:手機嗎,事件:收到簡訊,事件的訂閱者:我,事件處理器:去開會,訂閱關係:我訂閱手機
3、事件的聲明:分為詳細聲明和簡略聲明:
(1)詳細聲明:
public delegate void MyDelegateEventHandler(); public class Event { private MyDelegateEventHandler myDelegateEventHandler; public event MyDelegateEventHandler MyDelegate { add { this.myDelegateEventHandler += value; } remove { this.myDelegateEventHandler -= value; } } }
(2)簡略說明:
public delegate void MyDelegateEventHandler(); public class Event { public event MyDelegateEventHandler myDelegate; }
可以看到,在完整聲明中首先添加了一個委托類型的欄位,然後暴漏了添加和移除事件處理器的功能,但是我們經常用的是簡略聲明,因為代碼更加簡潔,
可以看出事件對外界隱藏了大部分功能,它的本質就是對其中委托欄位的一個封裝(encapsulation),防止外界偷用濫用委托欄位。
那麼問題來了:第一個問題:有了委托為什麼還會有事件呢,事件內部不就是委托嗎,原因是為了防止public型的委托欄位在外面被濫用,比如委托可以用invoke調用,
但是事件只能在+=或-=的左側,這樣就增加了整個程式的安全性。
第二個問題:那委托和事件的關係什麼樣的呢?我們說事件是基於委托的。一方面,事件需要委托來做一個約束,這個約束規定了事件源發送什麼要求給事件的訂閱者,
事件訂閱者的事件處理器必須和這個約束相對應才可以訂閱這個事件,另一方面,事件訂閱者收到事件以後做出事件處理器,而這個事件處理器必須通過委托才可以做到。
4、簡單實例:
Example:做一個視窗,有文本框和按鈕,點擊按鈕文本框顯示時間,不用WindowsForms
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace ConsoleApp14 { class Program { public static TextBox textBox; public static Button button; static void Main(string[] args) { Form form = new Form(); TextBox textBox = new TextBox(); Button button = new Button(); form.Controls.Add(textBox); form.Controls.Add(button); textBox.Width = 400; button.Top = 100; button.Click += Button_Click; form.ShowDialog(); } private static void Button_Click(object sender, EventArgs e) { textBox.Text = DateTime.Now.ToString(); } } }
這裡舉的事例就是windowsforms內部的代碼,我們說事件本身是不會發生的是由事件源內部的邏輯所觸發,在本例中,並不是人按了按鈕然後按鈕觸發了事件,
這其中還有一個小過程,就是當按鈕被key down再key up時,向程式內部發送了一系列電訊號,通知電腦,然後再發生事件,
5、聲明事件的相關約定:
用於聲明事件的委托一般用:事件+EvnetHandler,參數一般有2個,第一個事件源,第二個EventArgs的派生類,用於觸發事件的方法名一般為On+方法名,
訪問級別Protected。可能有點蒙,舉個實例就懂了。
Example:舉一個顧客在KFC點餐的例子
namespace ConsoleApp15 { class Program { static void Main(string[] args) { Customer customer = new Customer(); Waitor waitor = new Waitor(); customer.Order += waitor.Serve; customer.Eat(); customer.Pay(); } } public delegate void OrderEventHandler(Customer customer, OrderEventArgs e); public class Customer { public int Money { get; set; } public event OrderEventHandler Order; public void Pay() { Console.WriteLine($"OK,{Money} dollars"); } public void Eat() { Console.WriteLine("Let's go to the KFC..."); Console.WriteLine("Stand in front of the waitor..."); Console.WriteLine("A hamburger,Please..."); OnOrder(); } protected void OnOrder() { OrderEventArgs orderEventArgs = new OrderEventArgs(); orderEventArgs.Snack = "Hamburger"; orderEventArgs.Size = "large"; this.Order.Invoke(this, orderEventArgs); } } public class OrderEventArgs : EventArgs { public string Snack { get; set; } public string Size { get; set; } } class Waitor { public void Serve(Customer customer, OrderEventArgs e) { Console.WriteLine($"Here is your snack {e.Snack}"); int price = 20; switch (e.Size) { case "large": price *= 2; break; case "small": price *= 1; break; default: break; } customer.Money += price; } } }
按照事件的五個要素,首先需要事件源,做一個Customer類,還需要一個事件訂閱者,做一個Waitor類,然後根據訂閱關係去寫具體的方法,訂閱關係customer.Order += waitor.Serve; Customer點餐Waitor服務,waitor類中上餐並算好價格,這個時候需要一個事件處理器OrderEventHandler,這個委托的參數需要一個OrderEventArgs,創建這個類寫好屬性,在寫好委托和事件,然後在Customer類中寫點餐事件,點餐事件為Protected的,和public型的委托欄位一樣防止被外界濫用,提高安全性。
想融會貫通其實也不難,只需要將事件的5個要素每一個列舉出來,那麼最後事件也就出來了。
至此事件總結完畢,有不明之處還請指教。 2018-08-17 16:43:19