c# の 事件
1.事件的概念
事件是作為消i息的通知者,書寫方便,快捷。在模組之間劃定了清晰的界限,提高了應用程式的可維護性和重用性。
用白話說,就是“有事”發生了,然後事件作為通知者把發生的事儲存起來,然後再發給多個需要響應的觀察者。
這個沒做過的人,不大好理解:
打個比方:有一群賊,有毛賊、飛賊等等,而我是放哨的,所我也就是那個所謂“事件”。作為一個非常優秀的放哨的。我預先要把“有事發生”後的情況根據賊的種類進行儲存成相應的黑話,例如對於飛賊我要儲存–“從屋頂逃跑”,對於毛賊我要儲存–“從後門溜走”之類的黑話。這時候“有事”發生了–“主人回來了”或“警察來了”,我就通知飛賊“從屋頂逃跑”,通知毛賊“從後門溜走”……
我建議樓主看一看觀察者模式,事件其實就是在底層封裝了那個觀察者模式而已。而上面例子,放哨的就是通知者,賊就是觀察者,而主人和警察就是被觀察者。事件就是根據情況進行不同的響應,發出一系列不同或相同通知(訊息)給作為“觀察者”的類。
在以往我們編寫這類程式中,往往採用等待機制,為了等待某件事情的發生,需要不斷地檢測某些判斷變數,而引入事件程式設計後,大大簡化了這種過程:
2.事件需要注意的地方:
- 在類裡面宣告。
- 釋出者是一個類,訂閱者是一個類。
- 可以使用
+=
和-=
新增或者刪除委託。
釋出者和訂閱者模式:
釋出者:定義了一系列其他部分可能感興趣的事件。其他類可以 “註冊” 以獲取通知。
訂閱者: 當事件發生時,釋出者 “觸發事件”,然後執行訂閱者提交的所有事件。
3.例子
1.第一個事件例子
namespace VsCore_Demo {
public delegate void SaySomething (string name);
class Program {
public void SayHello (string name) {
Console.WriteLine ("Hello," + name + "!");
}
public void SayNiceToMeetYou (string name) {
Console.WriteLine ("Nice to meet you," + name + "!");
}
public event SaySomething come;
public event SaySomething come2;
public void test () {
//宣告兩個委託.
//宣告委託的時候,傳進去的引數是方法名。
SaySomething sayhello = new SaySomething (SayHello);
SaySomething saynice = new SaySomething (SayNiceToMeetYou);
//把兩個委託新增到事件裡
come += sayhello;
come += saynice;
//事件發生了。
//觸發事件是用事件直接加引數。
come ("張三");
System.Console.WriteLine("***********");
}
static void Main (string[] args) {
Program program = new Program ();
program.test ();
Console.Read ();
}
}
}
事件宣告是這樣的:
public event SaySomething come;
這樣表明了,come這個事件,只和SaySomething這個委託打交道。當事件發生的時候,由事件去呼叫這些個委託,然後由委託呼叫具體的實現方法。
例項化委託,注意我們用到了new關鍵字,就好像例項化一個類一樣,然後傳入一個引數,但這個引數不是string型別、也不是int型別,而是一個方法名。
SaySomething sayhello = new SaySomething (SayHello);
SaySomething saynice = new SaySomething (SayNiceToMeetYou);
我們回過頭來再看一下“事件”的定義:
public event SaySomething come;
這裡已經指出了“委託”的名字,所以,我們可以直接將方法加到事件上,而省略“委託”的例項化過程,因此上面的test()方法可以簡單寫為:
public void test()
{
come += SayHello;
come += SayNiceToMeetYou;
come("張三");
}
激發委託的時候,又回去了抽象了,直接把引數穿進去就行,中間是啥過程,他不管用。
委託+事件是觀察者模式的一個典型例子,所謂的委託其實就是觀察者,它會關心某種事件,一旦這種事件被觸發,這個觀察者就會行動
2. 事件完成:貓叫,主人醒,老鼠跑 的經典面試題
具體程式碼如下:
有幾點需要注意:
- CatCall?.Invoke(); 喚起事件;
- 事件 += 可以翻譯為 。貓叫引起了老鼠跑;
using System;
namespace DelegateDemo
{
//定義貓叫委託
public delegate void CatCallEventHandler();
public class Cat
{
//定義事件
public event CatCallEventHandler CatCall;
//定義喚醒事件的方法
public void OnCatCall()
{
Console.WriteLine("貓叫了一聲");
//喚醒事件。
CatCall?.Invoke();
}
}
public class Mouse
{
//定義老鼠跑掉方法
public void MouseRun()
{
Console.WriteLine("老鼠跑了");
}
}
public class People
{
//定義主人醒來方法
public void WakeUp()
{
Console.WriteLine("主人醒了");
}
}
class Program
{
static void Main(string[] args)
{
Cat cat = new Cat();
Mouse m = new Mouse();
People p = new People();
//關聯繫結
cat.CatCall += new CatCallEventHandler(m.MouseRun);
cat.CatCall += new CatCallEventHandler(p.WakeUp);
cat.OnCatCall();
Console.ReadKey();
}
}
}
3.蘋果降價的程式碼:
使用的是事件的標準形式
class Program
{
static void Main(string[] args)
{
Apple ap1 = new Apple()
{
Preice = 5288
};
//註冊事件
// 點了 += 以後,可以使用快捷鍵生成。
ap1.myEvent += PriceChanged;
//調整價格,觸發事件
ap1.Preice = 3999;
Console.ReadKey();
}
//事件響應程式
static void PriceChanged(object sender, MyEventArgs e)
{
Console.WriteLine("年終大促銷,iPhone 6 只賣 " + e.NewPrice +" 元, 原價 " + e.OldPrice + " 元,快來搶!"+sender.ToString());
}
}
/// <summary>
/// 事件引數類
/// </summary>
public class MyEventArgs : EventArgs
{
public MyEventArgs(decimal newPrice, decimal oldPrice)
{
this.NewPrice = newPrice;
this.OldPrice = oldPrice;
}
public readonly decimal NewPrice;
public readonly decimal OldPrice;
}
/// <summary>
/// 事件釋出者類
/// </summary>
public class Apple
{
private decimal price;
public decimal Preice
{
get
{
return price;
}
set
{
//如果價格變了,觸發事件通知使用者價格變了
if (price == value)
{
return;
}
decimal oldPrice = price;
price = value;
//呼叫觸發事件的方法。
//一般啟用方法是 On + event
OnRaiseEvet(new MyEventArgs(price, oldPrice));
}
}
public event EventHandler<MyEventArgs> myEvent;
//激發方法。
public virtual void OnRaiseEvet(MyEventArgs e)
{
//如果呼叫列表不為空,則觸發
if (myEvent != null)
{
myEvent(this, e);
//event關鍵字定義的事件只能由事件源物件自己激發,外界無法通過訪問委託變數直接激發事件。
//下面的程式碼無法編譯通過:Publisher p = new Publisher(); p.MyEvent(10);
}
}
}
關於事件
- 事件的主要目的是防止訂閱者之間相互干擾。
- 宣告事件,直接在委託前邊加 event
- 內外有別: 事件在類裡面的時候,可以當委託一樣用,而在類外邊,只能進行+= 和 – = 的操作
- 一般情況下,啟用事件的方法,都預設用 On+事件 命名
- 啟用使用 CatCall?.Invoke()
- 使用
event
來作為關鍵字,有什麼強制規定?(1)只能在包容類,才能傳送向訂閱者發出的委託,(2)類外邊不允許使用 =。 - sender 是用來輸出釋出者類的。
- 對於事件來說,外部只能註冊自己+=,登出自己-=,外界不可以登出其他的註冊者,
參考:
相關文章
- c# の datetimeC#
- DuiLib逆向分析の按鈕事件定位UI事件
- c#中的事件C#事件
- C#窗體--滑鼠事件C#事件
- C# - 委託與事件C#事件
- C#委託與事件C#事件
- c# 委託和事件C#事件
- C#基礎教程:事件C#事件
- 瞭解下C# 事件(Event)C#事件
- C#事件及響應方法概述C#事件
- 詳解C#委託與事件C#事件
- C#基礎之委託,事件C#事件
- 你太忙の
- 詳解C#委託和事件(二)C#事件
- 詳解C#委託和事件(一)C#事件
- C# Event (1) —— 我想搞個事件C#事件
- 求解 LCA の方法
- 晚上の決心
- C#規範整理·泛型委託事件C#泛型事件
- C# 從1到Core--委託與事件C#事件
- C#裡面標籤的屬性和事件C#事件
- C#總結(二)事件Event 介紹總結C#事件
- iconfontのsymbol的使用Symbol
- MyBatisPlusの效率與提升MyBatis
- 六等星の夜
- C# 委託原理刨析,外加和事件對比C#事件
- 春小麥の找人神器
- JS拾荒の字串JS字串
- JavaScript の querySelector 使用說明JavaScript
- C#學習筆記(補充)——擴充套件方法、事件C#筆記套件事件
- 徹底搞清楚c#中的委託和事件C#事件
- c#關於同步 /異常/多執行緒/事件 事例C#執行緒事件
- LeetCode のminimum-depth-of-binary-treeLeetCode
- 並查集の進階用法並查集
- 【canvas】動畫原理の胡克定律Canvas動畫
- 迴歸の一些想法
- 康託の複習筆記筆記
- C#快速入門教程(17)—— 委託、事件與Lambda表示式C#事件