[C#.NET] 建議 - 應該實現標準的事件模組寫法
我透過ReSharper,想要得知事件的宣告標準規則寫法。
我對按鈕控制項的Click按下F12
於是我得到了。
public event EventHandler Click
而 EventHandler 的委派原型長得如下,這也是絕大部份 .NET BCL 所使用的原型。
public delegate void EventHandler(object sender, EventArgs e);
sender,所代表的就是事件的觸發者,button就是觸發者
e,所代表的就是事件參數,按扭按下去就是事件參數
EventArgs 則是事件的參數的基礎原型
用來觸發事件的OnClick方法
如果還看不太懂,我們再來看 textBox 的 MouseDown事件好了
MouseEventHandler 原型長這樣
public delegate void MouseEventHandler(object sender, MouseEventArgs e);
MouseEventArgs 事件參數長這樣
再多看看幾個控制項類別以及方法,就會規納出幾個重點
- 事件委派的命名以 EventHandler 結尾
- 事件委派的簽章不返回任何資料型態,即宣告成 void
- 事件委派委派的簽章具有兩個參數,sender 表示事件觸發者;e 表示事件參數
- 事件參數的命名以 EventArgs 結尾
- 事件觸發的方法命名以 On 為開頭,用來引發事件用。
更多的資源可以參考下篇,由上圖可以得知,微軟是遵守其規則。
http://msdn.microsoft.com/zh-tw/library/ms229011.aspx
接下來,練習一下剛剛的規則啦~
Step1.建立 ConnectCompletedEventArgs 類別,並繼承 EventArgs
{
private bool _isConnected;
public bool IsConnected
{
get { return _isConnected; }
set { _isConnected = value; }
}
}
Step2.建立Reader類別,分別建立 ConnectCompletedEventHandler 委派和 ConnectCompleted 事件
public event ConnectCompletedEventHandler ConnectCompleted;
Step3.在Reader類別,建立公開的Connect方法及受保護的OnConnect方法
{
ConnectCompletedEventArgs e = new ConnectCompletedEventArgs();
//模擬長時間作業
Thread.Sleep(10000);
e.IsConnected = true;
this.OnConnect(e);
}
protected virtual void OnConnect(ConnectCompletedEventArgs e)
{
if (ConnectCompleted != null)
{
ConnectCompleted(this, e);
}
}
最後完成的程式碼如下:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace RfidReader
{
public class Reader
{
public delegate void ConnectCompletedEventHandler(object sender, ConnectCompletedEventArgs e);
public event ConnectCompletedEventHandler ConnectCompleted;
public void Connect()
{
ConnectCompletedEventArgs e = new ConnectCompletedEventArgs();
//模擬長時間作業
Thread.Sleep(10000);
e.IsConnected = true;
this.OnConnect(e);
}
protected virtual void OnConnect(ConnectCompletedEventArgs e)
{
if (ConnectCompleted != null)
{
ConnectCompleted(this, e);
}
}
}
public class ConnectCompletedEventArgs : EventArgs
{
private bool _isConnected;
public bool IsConnected
{
get { return _isConnected; }
set { _isConnected = value; }
}
}
}
Step4.在Client呼叫端就可以使用 += 來註冊(訂閱) ConnectCompleted 事件。
{ Reader reader = new Reader(); reader.ConnectCompleted += new Reader.ConnectCompletedEventHandler(reader_ConnectCompleted); reader.Connect(); } private void reader_ConnectCompleted(object sender, ConnectCompletedEventArgs e) { MessageBox.Show(e.IsConnected.ToString()); }
然而,MSDN上又建議我們『要使用 System.EventHandler<T>,而不要手動建立新的委派來當做事件處理常式使用。』
所以把 Step2. 上的委派(delegate)刪掉,把事件宣告改成以下:
Client的註冊改成以下:
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET