免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
事件與委托趣談
事件與委托趣談收藏
 
事件與委托似乎很難以理解,這是因為它們的使用方式與常用的編碼有很大的差別,例如通常編寫的都是同步代碼,調(diào)用一個類型的方法,會即刻出現(xiàn)方法執(zhí)行的結(jié)果,這是符合邏輯的。但在某些情況中,同步代碼未必滿足需求,拿公共汽車來打個比方,如果交通管制中心希望每一輛公車到達一個站點時都發(fā)送給自己一個信號以便自己能夠隨時掌握交通狀況,使用同步代碼,公汽對象肯定需要調(diào)用管制中心對象,這樣就出現(xiàn)了我們一直不愿意看到的情況:兩個類型緊密地耦合在一起。既然要其它類型對自己的行為作出反應(yīng),親自調(diào)用其類型的方法似乎不可避免,在同步代碼中,很難避免這種緊密的類型調(diào)用關(guān)系。
另一個差別是在一般情況下,我們只將屬性作為參數(shù)傳遞給方法,而很少會考慮將一個方法傳遞給另一個方法。
 
我們拋棄各種C#參考書中桀驁難懂的事件與委托概念,設(shè)想一個情景來理解事件與委托的使用:有一家IT公司,董事長不希望自己的雇員在上班時間玩游戲,但又不可能每時每刻都盯著每個雇員,因此,他希望使用一種新的方式實現(xiàn)監(jiān)視雇員的效果:如果有雇員違反規(guī)定,某個設(shè)備或?qū)iT的監(jiān)查人員將自動發(fā)出一個消息通知他,董事長只需要在事情發(fā)生時進行處理。
因此,這個用例實際上是兩種類型——董事長類與雇員類——之間的交互,下面的代碼將給讀者展示如何使用委托與事件機制實現(xiàn)這種交互:
首先,我們需要在董事長類與雇員類之間定義一個委托類型,用于傳遞兩者之間的事件,這個類型就是一個監(jiān)視設(shè)備或?qū)iT負責(zé)打小報告的監(jiān)查人員:
public delegate void DelegateClassHandle();
定義一個委托的過程類似方法的定義,但它沒有方法體。定義委托一定要添加關(guān)鍵字delegate。由于定義委托實際上相當(dāng)一個類,因此可以在定義類的任何地方定義委托。另外,根據(jù)委托的可見性,也可以添加一般的訪問修飾符,如public、private和protected。
委托的返回值類型為void,這并非表示委托類型本身帶有返回值,該返回值類型是指委托的目標(biāo)函數(shù)類型,即它委托的一個事件處理函數(shù)返回值是void類型。
新建一個雇員類Employee,其代碼如下:
public class Employee
{
    public event DelegateClassHandle PlayGame;
 
    public void Games()
    {
        if (PlayGame != null)
        {
            PlayGame();
        }
    }
}
雇員類Employee代碼中定義了一個DelegateClassHandle類型的事件PlayGame,它的定義方式也很特殊,首先必須使用關(guān)鍵字event,表示PlayGame是一個事件,同時還必須聲明該事件的委托類型為DelegateClassHandle,即將來由該類型的委托對象負責(zé)通知事件。
如果有雇員開始玩游戲,它將執(zhí)行Games方法,而只要該方法一被調(diào)用,就會觸發(fā)一個事件PlayGame,然后董事長就會收到這個事件的消息——有人在玩游戲了。
董事長類代碼如下,他有一個方法Notify用于接收消息:
public class Admin
{
    public void Notify()
    {
        System.Console.WriteLine("someone is playing game");
    }
}
Employee的PlayGame事件如何與Admin的Notify方法關(guān)聯(lián)起來呢?只需通過事件綁定即可實現(xiàn),具體過程如下列代碼:
Employee employee = new Employee();
Admin admin = new Admin();
 
employee.PlayGame += new DelegateClassHandle(admin.Notify);
employee.Games();
請大家注意事件綁定的代碼:
employee.PlayGame += new DelegateClassHandle(admin.Notify);
通過DelegateClassHandle將兩個類的交互進行了綁定,當(dāng)employee.Games方法調(diào)用后,觸發(fā)PlayGame事件,而該事件將被委托給admin的Notify方法處理,通知董事長有雇員在上班時間玩游戲。
但董事長并不滿足這種簡單的通知,他還想知道究竟是誰在上班時間違反規(guī)定。顯然,現(xiàn)在委托對象必須傳遞必要的參數(shù)才行,這個要求也可以很容易地辦到。事件的參數(shù)可以設(shè)置為任何類型的數(shù)據(jù),在.NET框架中,還提供了事件參數(shù)基類EventArgs專門用于傳遞事件數(shù)據(jù)。
從該EventArgs類派生一個自定義的事件參數(shù)類CustomeEventArgs,這個類型將攜帶雇員姓名和年齡信息:
public class CustomeEvetnArgs : EventArgs
{
    string name = "";
    int age = 0;
    public CustomeEvetnArgs()
    { }
    public string Name
    {
        get { return this.name; }
        set { this.name = value; }
    }
    public int Age
    {
        get { return this.age; }
        set { this.age = value; }
    }
}
修改委托類型DelegateClassHandle的定義,讓其攜帶必要的參數(shù):
public delegate void DelegateClassHandle(object sender, CustomeEvetnArgs e);
雇員類的代碼修改后如下:
public class Employee
{
    private string _name;
 
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
    private int _age;
 
    public int Age
    {
        get { return _age; }
        set { _age = value; }
    }
 
    public event DelegateClassHandle PlayGame;
 
    public void Games()
    {
        if (PlayGame != null)
        {
            CustomeEvetnArgs e = new CustomeEvetnArgs();
            e.Name = this._name ;
            e.Age = this._age;
            PlayGame(this, e);
        }
    }
}
在Games方法中,首先新建一個CustomeEventArgs對象,然后設(shè)置了必要的屬性Name和Age。
董事長的通知方法也必須相應(yīng)地進行修改:
public class Admin
{
    public void Notify(object sender, CustomeEvetnArgs e)
    {
        System.Console.WriteLine(e.Name+" is "+e.Age.ToString());
    }
}
將兩個類型對象進行關(guān)聯(lián)的代碼也需要進行相應(yīng)的修改:
Employee employee = new Employee();
employee.Name = "Mike";
employee.Age = 25;
Admin admin = new Admin();
 
employee.PlayGame += new DelegateClassHandle(admin.Notify);
employee.Games();
修改后的代碼運行的結(jié)果是,當(dāng)Mike調(diào)用Games方法玩游戲時,會自動觸發(fā)PlayGame事件,而該事件攜帶相關(guān)信息通知admin,后者的Notify方法將接收到數(shù)據(jù)并輸出“Mike is 25”,告訴董事長是Mike,25歲,正在上班時間玩游戲。
 
委托是可以多路廣播(Mulitcast)的,即一個事件可以委托給多個對象接收并處理。在上面的用例中,如果有另一位經(jīng)理與董事長具有同樣的癖好,也可以讓委托對象將雇員的PlayGame事件通知他。
首先定義經(jīng)理類:
public class Manager
{
    public void Notify(object sender, CustomeEvetnArgs e)
    {
        System.Console.WriteLine(sender.ToString() + "-" + e.Name);
    }
}
經(jīng)理Manager類型的Notify方法與Admin一致,他也接受到相應(yīng)的信息。
委托的多路廣播綁定的方法仍然是使用+=運算符,其方法如下面的代碼所示:
Employee employee = new Employee();
employee.Name = "Mike";
employee.Age = 25;
Admin admin = new Admin();
Manager manager = new Manager();
 
employee.PlayGame += new DelegateClassHandle(admin.Notify);
employee.PlayGame += new DelegateClassHandle(manager.Notify);
employee.Games();
執(zhí)行該方法,讀者將看到admin和manager的Notify方法都會被事件通知并調(diào)用執(zhí)行。通過這樣的方法,董事長和經(jīng)理都會知道Mike在玩游戲了。
如果董事長不希望經(jīng)理也收到這個通知,該如何解除PlayGame對manager的事件綁定呢?同樣非常簡單,在employee.Games方法被調(diào)用前執(zhí)行下列語句即可:
employee.PlayGame -= new DelegateClassHandle(manager.Notify);
 
最后需要提醒讀者注意的,Employee類中的Games方法在觸發(fā)事件PlayGame之前需要判斷該事件是否為null。當(dāng)employee對象的Games方法觸發(fā)事件PlayGame后,必須有一個目標(biāo)函數(shù)來處理這個事件,而該語句正是判斷該目標(biāo)函數(shù)是否存在。如果將這個判斷去掉,且對事件不進行任何綁定而直接調(diào)用Games方法,程序?qū)⒃谑录layGame處彈出一個NullReferenceException的異常。
讀者能夠從委托與事件的代碼中得出什么結(jié)論嗎?兩個需要存在調(diào)用關(guān)系的類型,在各自的實現(xiàn)中卻沒有編寫實際的調(diào)用代碼,它們只是通過一個事件和一個第三方的委托類型完成了消息的傳遞過程。兩個類型之間不存在任何的緊密耦合,它們看似松散地通過一個委托對象中通信,實現(xiàn)了本書一直宣傳的“高聚合”和“低耦合”觀點。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
委托與事件的關(guān)系
通俗的事件委托解釋
例子:用委托實現(xiàn)事件
面試中的事件
SSM前后端分離/不分離對比Demo
基于 SpringBoot MyBatis 前后端分離實現(xiàn)的在線辦公系統(tǒng)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服