詳解C#之事件
事件:定義了事件成員的類允許通知其他其他對(duì)象發(fā)生了特定的事情。具體的說(shuō),定義了事件成員的類能提供以下功能
1.方法能登記它對(duì)事件的關(guān)注
2.方法能注銷它對(duì)事件的關(guān)注
3.事件發(fā)生時(shí),登記了的方法將收到通知
類型之所以能提供事件通知功能,是因?yàn)轭愋途S護(hù)了一個(gè)已登記方法的列表。事件發(fā)生后,類型將通知列表中所有已登記的方法。
事件是以委托為基礎(chǔ)。委托是調(diào)用回調(diào)方法的一種類型安全的方式。對(duì)象憑借回調(diào)方法接收他們訂閱的通知。
假如有一下場(chǎng)景:要設(shè)計(jì)一個(gè)電子郵件程序。當(dāng)有新的郵件的到達(dá)時(shí),用戶希望做些一別的操作,例如轉(zhuǎn)發(fā)給其他人或其他想實(shí)現(xiàn)的功能。事件在其中起到的就是一個(gè)通知的作用,告訴其他對(duì)象有新的郵件到達(dá)了,可以做XXX事情了。
下面使用事件實(shí)現(xiàn)這個(gè)功能
1.定義一個(gè)附加信息類,用來(lái)通知接收者發(fā)生了什么。
/// <summary>
/// 事件附加消息
/// </summary>
public class NewMailEventArgs:EventArgs{
private readonly string m_from,m_to,m_subject;
public NewMailEventArgs(string from,string to,string subject){
m_from=from;
m_to=to;
m_subject=subject;
}
// 發(fā)件人
public string From { get{return m_from;} }
// 接收人
public string To { get{return m_to;} }
// 主題
public string Subject{get{return m_subject;}}
}
附加信息類繼承了EventArgs,這個(gè)基類只定義了一個(gè)空的信息,在沒(méi)有附加信息時(shí)可直接使用EventArgs.Empty。EventArgs類的源代碼
namespace System
{
//
// Summary:
// Represents the base class for classes that contain event data, and provides a
// value to use for events that do not include event data.
public class EventArgs
{
//
// Summary:
// Provides a value to use with events that do not have event data.
public static readonly EventArgs Empty;
//
// Summary:
// Initializes a new instance of the System.EventArgs class.
public EventArgs();
}
}
2.定義事件成員
事件成員使用C#關(guān)鍵字event定義。每個(gè)事件成員都要指定以下內(nèi)容:可訪問(wèn)標(biāo)識(shí)符public(因?yàn)橹挥衟ubli才能使其他對(duì)象訪問(wèn)),委托類型以及名稱。
public class MailManager{
// 定義事件成員
public event EventHandler<NewMailEventArgs> NewMail;
}
它的類型是EventHandler<NewMailEventArgs> 這意味著事件通知的所有接收者都必須有一個(gè)和這個(gè)類型匹配的回調(diào)方法。System.EventHandler的委托定義類型如下:
namespace System
{
//
// Summary:
// Represents the method that will handle an event when the event provides data.
//
// Parameters:
// sender:
// The source of the event.
//
// e:
// An object that contains the event data.
//
// Type parameters:
// TEventArgs:
// The type of the event data generated by the event.
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
}
所以接收者必須提供的方法必須是一下形式:
void MethodName(Object sender,NewMailEventArgs e);
3. 定義負(fù)責(zé)引發(fā)事件的方法來(lái)通知事件的登記對(duì)象
public class MailManager{
// 定義事件成員
public event EventHandler<NewMailEventArgs> NewMail;
// 定義負(fù)責(zé)引發(fā)事件的方法來(lái)通知已登記的對(duì)象
protected virtual void OnNewMail(NewMailEventArgs e){
// 將字段復(fù)制到一個(gè)臨時(shí)變量,避免多線程情況中這個(gè)成員被移除
EventHandler<NewMailEventArgs> temp=Volatile.Read(ref NewMail);
if(temp!=null) temp(this,e);
}
// 接受附加信息并調(diào)用引發(fā)事件的方法來(lái)通知所有登記的對(duì)象
public void SimulateNewMail(string from,string to,string subject){
NewMailEventArgs e=new NewMailEventArgs(from,to,subject);
OnNewMail(e);
}
}
4. 定義事件接收者
public class Fax{
public Fax(MailManager mm){
// 構(gòu)造委托實(shí)例,向事件登記回調(diào)方法
mm.NewMail+=FaxMsg;
}
/// <summary>
/// 回調(diào)方法
/// </summary>
/// <param name="sender">表示MailManager對(duì)象,便于將信息傳遞給他</param>
/// <param name="e">表示MailManager對(duì)象想傳給我們的附加信息</param>
private void FaxMsg(object sender,NewMailEventArgs e){
Console.WriteLine("msg:{0},{1},{2}",e.From,e.To,e.Subject);
}
/// <summary>
/// 注銷對(duì)事件的登記
/// </summary>
/// <param name="mm"></param>
public void Unregister(MailManager mm){
mm.NewMail-=FaxMsg;
}
}
對(duì)象不在接收事件通知時(shí)應(yīng)注銷對(duì)事件的關(guān)注。因?yàn)閷?duì)象只要向事件等急了它的一個(gè)方法,便不能被垃圾回收。
5. 程序初始化時(shí)應(yīng)首先構(gòu)造MailManager對(duì)象,將指向它的變量傳遞給Fax。在Fax構(gòu)造器中添加對(duì)事件的關(guān)注。最后調(diào)用MailManager對(duì)象的事件通知方法
static void Main(string[] args)
{
MailManager mm=new MailManager();
Fax f=new Fax(mm);
mm.SimulateNewMail("a","b","Hello World!");
Console.ReadKey();
}
控制臺(tái)輸出結(jié)果:以調(diào)用回調(diào)方法。

以上就是詳解C#之事件的詳細(xì)內(nèi)容,更多關(guān)于C#之事件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#通過(guò)html調(diào)用WinForm的方法
這篇文章主要介紹了C#通過(guò)html調(diào)用WinForm的方法,涉及html頁(yè)面中使用JavaScript訪問(wèn)C#的相關(guān)技巧,需要的朋友可以參考下2016-04-04
常用.NET工具(包括.NET可再發(fā)行包2.0)下載
常用.NET工具(包括.NET可再發(fā)行包2.0)下載...2007-03-03
WPF仿三星手機(jī)充電界面實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了WPF仿三星手機(jī)充電界面實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-08-08
C#常用數(shù)據(jù)結(jié)構(gòu)之?dāng)?shù)組Array
這篇文章介紹了C#常用數(shù)據(jù)結(jié)構(gòu)之?dāng)?shù)組Array,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05
C# List 并發(fā)丟數(shù)據(jù)問(wèn)題原因及解決方案
這篇文章主要介紹了C# List 并發(fā)丟數(shù)據(jù)問(wèn)題原因及解決方案,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2021-02-02
c# 編寫一個(gè)輕量級(jí)的異步寫日志的實(shí)用工具類(LogAsyncWriter)
這篇文章主要介紹了c# 如何編寫一個(gè)輕量級(jí)的異步寫日志的實(shí)用工具類(LogAsyncWriter),幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-03-03

