C#里的委托和事件实现 (转)
生活随笔
收集整理的這篇文章主要介紹了
C#里的委托和事件实现 (转)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一篇被轉爛了的文章,也不差我一個
委托就是..............去執行一個方法?
一、委托的簡介
1、委托的聲明:
<access modifier> delegate <returnType> HandlerName ([parameters])
例如:
public delegate void PrintHandler(string str);
??????委托聲明定義了一種類型,它用一組特定的參數以及返回類型來封裝方法。對于靜態方法,委托對象封裝要調用的方法。對于實例方法,委托對象同時封裝一個實例和該實例上的一個方法。如果您有一個委托對象和一組適當的參數,則可以用這些參數調用該委托。
2、委托的使用:
using System;
public class MyClass
{
????????????????public static void Main()
????????????????{
????????????????????????????????PrintStr myPrinter = new PrintStr();
????????????????????????????????PrintHandler myHandler = null;
????????????????????????????????myHandler += new PrintHandler(myPrinter.CallPrint); // 將委托鏈接到方法,來實例化委托
????????????????????????????????if(myHandler!=null)
????????????????????????????????????????????????myHandler("Hello World!");????// 調用委托,相當于匿名調用委托所鏈接的方法
????????????????????????????????Console.Read();
????????????????}
}
public delegate void PrintHandler(string str);????// 聲明委托類型
public class PrintStr
{???????????????
????????????????public void CallPrint(string input)
????????????????{
????????????????????????????????Console.WriteLine(input);
????????????????}
}
在C#中使用委托方法:
·??????????創建委托所使用的方法必須和委托聲明相一致(參數列表、返回值都一致)
·??????????利用 +=、-=來進行委托的鏈接、取消鏈接或直接使用Delegate.Combine和Delegate.Remove方法來實現
·??????????可以使用MulticastDelegate的實例方法GetInvocationList()來獲取委托鏈中所有的委托
·??????????不能撰寫包含 out 參數的委托
二、事件的簡介
C# 中的“事件”是當對象發生某些事情時,類向該類的客戶提供通知的一種方法。
1、事件的聲明:
聲明的格式為:<access modifier> event <delegate type> EventName
????????因為使用委托來聲明事件,所以在類里聲明事件時,首先必須先聲明該事件的委托類型<delegate type>(如果尚未聲明的話)。在上面我們已經提到過了委托類型的聲明,但是在.net??framework下為事件使用的委托類型進行聲明時有更嚴格的規定:
(1)、 事件的委托類型應采用兩個參數;
(2)、兩個參數分別是:指示事件源的“對象源”參數和封裝事件的其他任何相關信息的“e”參數;
(3)、“e”參數的類型應為EventArgs 類或派生自 EventArgs 類。
如下的定義:
public delegate void PrintHandler(object sender,System.EventArgs e);
然后我們才能聲明該委托類型的事件
例如:
public event PrintHandler Print;
當事件發生時,將調用其客戶提供給它的委托。
2、調用事件:
????????類聲明了事件以后,可以就像處理所指示的委托類型的字段那樣處理該事件。如果沒有任何客戶將委托與該事件綁定,則該字段將為空;否則該字段引用應在調用該事件時調用的委托。因此,調用事件時通常先檢查是否為空,然后再調用事件。(調用事件,即觸發事件,只能從聲明該事件的類內進行)
if(Print != null)
{
????????????????Print (this,e);
}
3、事件綁定:
????????從類的外面來看,事件就象類的一個公共成員,通過 類名.事件名 的形式來訪問,但是只能對它做綁定和解除綁定的操作,而不能有其他操作。
類名. Print += new PrintHandler(綁定的方法名)??// 將某個方法綁定到Print事件上
類名. Print??-= new PrintHandler(綁定的方法名)??// 將某個已綁定到Print事件上的方法從Print事件上解除
三、委托和事件的使用
委托和事件在用戶界面程序里用的比較的多,比如象在winform或webform的用戶UI上的button和它的click事件:
// 將Button1_Click()方法綁定到按鈕控件Button1的Click事件上
this.Button1.Click += new System.EventHandler(this. Button1_Click);
private void Button1_Click(object sender, System.EventArgs e)????// Button1_Click()方法
{
????????????????……??
}
然而除了用戶界面程序外,在很多其他地方也用到了事件驅動模式,比如觀察者模式(Observer)或發布/訂閱(Publish/Subscribe)里:在一個類里發布(Publish)某個可以被觸發的事件,而其他的類就可以來訂閱(Subscribe)該事件。一旦這個發布者類觸發了該事件,那么運行時環境會立刻告知所有訂閱了該事件的訂閱者類:這個事件發生了!從而各個訂閱者類可以作出它們自己的反應(調用相應方法)。
我們來舉一個生活中的實際例子來說明如何使用委托和事件,以及使用委托和事件所帶來的好處:
比如說有一個公司(場景),你是老板,手下有主管和員工,作為老板你會指派(委托)主管管理員工的工作,如果某個員工玩游戲,則讓某個主管從該員工的薪水里扣去500元錢。
這就是現實中的委托。
而在寫程序中,假設程序員就是老板,有兩個類分別為主管和員工,而主管小王和員工小張就是兩個類的對象實例。員工類有一個方法:玩游戲,同時就有一個玩游戲的事件,他一玩游戲就會激發這個事件。而主管類就是負責處理該事件的,他負責把玩游戲的員工的薪水扣除500。
(一)、首先,我們來看看在非委托的情況下比較常見的一種設計方式(當然這不是唯一的方式,也不是最好的方式,但是很常見):
using System;
namespace CSharpConsole
{
????????????????public class 場景
????????????????{
????????????????????????????????[STAThread]
????????????????????????????????public static void Main(string[] args)
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("場景開始了.");
????????????????????????????????????????????????// 生成主管類的對象實例 小王
????????????????????????????????????????????????主管 小王 = new 主管();
????????????????????????????????????????????????// 生成員工類的對象實例 小張,指定他的主管
????????????????????????????????????????????????員工 小張 = new 員工(小王);
????????????????????????????????
????????????????????????????????????????????????Console.WriteLine("該員工本有的薪水:" + 小張.薪水.ToString());
????????????
????????????????????????????????????????????????// 員工開始玩游戲
????????????????????????????????????????????????小張.玩游戲();
????????????????????????????????????????????????Console.WriteLine("現在該員工還剩下:" +小張.薪水.ToString());
????????????????????????????????
????????????????????????????????????????????????Console.WriteLine("場景結束");
????????????????????????????????????????????????Console.ReadLine();
????????????????????????????????}
????????????????}
????????????????// 負責扣錢的人----主管
????????????????public class 主管
????????????????{
????????????????????????????????public 主管()
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("生成主管");
????????????????????????????????}
????????????????????????????????public void 扣薪水(員工 employee)
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("主管:好小子,上班時間膽敢玩游戲");
????????????????????????????????????????????????Console.WriteLine("主管:看看你小子有多少薪水");
????????????????????????????????
????????????????????????????????????????????????Console.WriteLine("開始扣薪水...");
????????????????????????????????????????????????System.Threading.Thread.Sleep(1000);
????????????????????????????????????????????????employee.薪水 = employee.薪水 - 500;
????????????????????????????????????????????????Console.WriteLine("扣薪水執行完畢.");???????????
????????????????????????????????}
????????????????}
????????????????// 如果玩游戲,則會引發事件
????????????????public class 員工
????????????????{
????????????????????????????????// 保存員工的薪水
????????????????????????????????private int m_Money;
????????????????????????????????// 保存該員工的主管
????????????????????????????????private 主管 m_Manager;
????????????????????????????????public 員工(主管 manager)
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("生成員工.");
????????????????????????????????????????????????m_Manager = manager;??// 通過構造函數,初始化員工的主管。
????????????????????????????????????????????????m_Money = 1000; // 通過構造函數,初始化員工的薪水。
????????????????????????????????}
????????????????????????????????public int 薪水 // 此屬性可以操作員工的薪水 。
????????????????????????????????{
????????????????????????????????????????????????get
????????????????????????????????????????????????{
????????????????????????????????????????????????????????????????return m_Money;
????????????????????????????????????????????????}
????????????????????????????????????????????????set
????????????????????????????????????????????????{
????????????????????????????????????????????????????????????????m_Money = value;
????????????????????????????????????????????????}
????????????????????????????????}
????????????????????????????????public void 玩游戲()
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("員工開始玩游戲了..");
????????????????????????????????????????????????Console.WriteLine("員工:CS真好玩,哈哈哈! 我玩...");
????????????????????????????????????????????????System.Threading.Thread.Sleep(1000);
????????????????????????????????????????????????
????????????????????????????????????????????????m_Manager. 扣薪水(this);
????????????????????????????????}
????????????????}
}
這種方法所帶來的問題: 員工類和主管類的耦合性太高
1、???在客戶程序里必須先創建了主管類之后才能生成員工類,如果在不需要主管類對象而只需員工類對象的地方,為了創建所需的員工類對象實例,你也不得不去先創建一個主管類的對象實例;
2、???如果場景劇本(即客戶程序需求)發生了變化
(1)、現在要讓一個新的角色(一個新的類),如保安,來代替主管,負責在員工玩游戲時扣員工薪水,那么我們不得不去修改員工類,或許還需要修改主管類;
(2)、如果場景劇本增加新的需求,要求員工在玩游戲后,不但要扣薪水,還要在績效上扣分,那么我們也不得不修改員工類。
(二)、利用委托的實現:
下面有個例子:在C# 控制臺應用程序編輯運行成功:
using System;
namespace CSharpConsole
{
????????????????// 定義委托
????????????????public delegate void PlayGameHandler(object sender,System.EventArgs e);
????????????????// 負責扣錢的人----主管
????????????????public class 主管
????????????????{
????????????????????????????????public 主管()
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("生成主管");
????????????????????????????????}
????????????????????????????????public void 扣薪水(object sender,EventArgs e)
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("主管:好小子,上班時間膽敢玩游戲");
????????????????????????????????????????????????Console.WriteLine("主管:看看你小子有多少薪水");
????????????????
????????????????????????????????????????????????員工 employee = (員工)sender;
????????????????
????????????????????????????????????????????????Console.WriteLine("開始扣薪水...");
????????????????????????????????????????????????System.Threading.Thread.Sleep(1000);
????????????????????????????????????????????????employee.薪水 = employee.薪水 - 500;
????????????????????????????????????????????????Console.WriteLine("扣薪水執行完畢.");???????????
????????????????????????????????}
????????????????}
????????????????// 如果玩游戲,則會引發事件
????????????????public class 員工
????????????????{
????????????????????????????????// 先定義一個事件,這個事件表示員工在玩游戲。
????????????????????????????????public event PlayGameHandler PlayGame;
????????????????????????????????// 保存員工薪水的變量
????????????????????????????????private int m_Money;
????????????????????????????????public 員工()
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("生成員工.");
????????????????????????????????????????????????m_Money = 1000; // 構造函數,初始化員工的薪水。
????????????????????????????????}
????????????????????????????????public int 薪水 // 此屬性可以操作員工的薪水 。
????????????????????????????????{
????????????????????????????????????????????????get
????????????????????????????????????????????????{
????????????????????????????????????????????????????????????????return m_Money;
????????????????????????????????????????????????}
????????????????????????????????????????????????set
????????????????????????????????????????????????{
????????????????????????????????????????????????????????????????m_Money = value;
????????????????????????????????????????????????}
????????????????????????????????}
????????????????????????????????public void 玩游戲()
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("員工開始玩游戲了..");
????????????????????????????????????????????????Console.WriteLine("員工:CS真好玩,哈哈哈! 我玩...");
????????????????????????????????????????????????System.Threading.Thread.Sleep(1000);
????????????????????????????????????????????????System.EventArgs e = new EventArgs();
????????????????????????????????????????????????OnPlayGame(e);
????????????????????????????????}
????????????????????????????????protected virtual void OnPlayGame(EventArgs e)
????????????????????????????????{
????????????????????????????????????????????????if(PlayGame != null)
????????????????????????????????????????????????{
????????????????????????????????????????????????????????????????PlayGame(this,e);
????????????????????????????????????????????????}
????????????????????????????????}
????????????????}
????????????????public class 場景
????????????????{
????????????????????????????????[STAThread]
????????????????????????????????public static void Main(string[] args)
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("場景開始了.");
????????????????????????????????????????????????// 生成主管類的對象實例 小王
????????????????????????????????????????????????主管 小王 = new 主管();
????????????????????????????????????????????????// 生成員工類的對象實例 小張
????????????????????????????????????????????????員工 小張 = new 員工();
????????????????????????????????????????????????// 設下委托,指定監視
????????????????????????????????????????????????小張.PlayGame += new PlayGameHandler(小王. 扣薪水);
????????????????????????????????
????????????????????????????????????????????????Console.WriteLine("該員工本有的薪水:" + 小張.薪水.ToString());
????????????
????????????????????????????????????????????????// 員工開始玩游戲
????????????????????????????????????????????????小張.玩游戲();
????????????????????????????????????????????????Console.WriteLine("現在該員工還剩下:" +小張.薪水.ToString());
????????????????????????????????
????????????????????????????????????????????????Console.WriteLine("場景結束");
????????????????????????????????????????????????Console.ReadLine();
????????????????????????????????}
????????????????}
}
對于前面提出的問題:
1、???解耦了主管類和員工類之間的必然聯系,可以單獨創建員工類對象實例,而不用管是否有主管類對象實例的存在;
2、???在客戶程序需求變化時:
(1)、我們只需修改客戶程序,即上面例子里的class 場景,將委托改為如下:
保安 小李 = new 保安();
小張.PlayGame += new PlayGameHandler(小李. 扣薪水);
即可實現由保安來負責扣薪水的需求變化,而不用動員工類。
(2)、我們只需修改客戶程序,即上面例子里的class 場景,添加一個如下的委托:
????????????????小張.PlayGame += new PlayGameHandler(某某. 扣績效分);
這個“某某”可以是主管,也可以是其他新的角色(新的類),只需要在“某某”對應的類里定義扣績效分的動作即可,而不用動員工類。
四、總結:
??????當然,不使用委托和事件我們仍然可以設計出解耦的類,然而卻會增加很多的類、接口以及關聯等等,增加了代碼量和程序的邏輯復雜性,而在.net里利用委托和事件我們只需少的多的代碼來實現。
??委托和事件的使用有如下幾個要素:
1、激發事件的對象-----就是員工小張
2、處理對象事件的對象-----就是主管小王
3、定義委托,就是你讓主管小王監視員工小張。
如果這三個要素都滿足的話,則你就寫出了一個完整事件的處理。??
委托就是..............去執行一個方法?
一、委托的簡介
1、委托的聲明:
<access modifier> delegate <returnType> HandlerName ([parameters])
例如:
public delegate void PrintHandler(string str);
??????委托聲明定義了一種類型,它用一組特定的參數以及返回類型來封裝方法。對于靜態方法,委托對象封裝要調用的方法。對于實例方法,委托對象同時封裝一個實例和該實例上的一個方法。如果您有一個委托對象和一組適當的參數,則可以用這些參數調用該委托。
2、委托的使用:
using System;
public class MyClass
{
????????????????public static void Main()
????????????????{
????????????????????????????????PrintStr myPrinter = new PrintStr();
????????????????????????????????PrintHandler myHandler = null;
????????????????????????????????myHandler += new PrintHandler(myPrinter.CallPrint); // 將委托鏈接到方法,來實例化委托
????????????????????????????????if(myHandler!=null)
????????????????????????????????????????????????myHandler("Hello World!");????// 調用委托,相當于匿名調用委托所鏈接的方法
????????????????????????????????Console.Read();
????????????????}
}
public delegate void PrintHandler(string str);????// 聲明委托類型
public class PrintStr
{???????????????
????????????????public void CallPrint(string input)
????????????????{
????????????????????????????????Console.WriteLine(input);
????????????????}
}
在C#中使用委托方法:
·??????????創建委托所使用的方法必須和委托聲明相一致(參數列表、返回值都一致)
·??????????利用 +=、-=來進行委托的鏈接、取消鏈接或直接使用Delegate.Combine和Delegate.Remove方法來實現
·??????????可以使用MulticastDelegate的實例方法GetInvocationList()來獲取委托鏈中所有的委托
·??????????不能撰寫包含 out 參數的委托
二、事件的簡介
C# 中的“事件”是當對象發生某些事情時,類向該類的客戶提供通知的一種方法。
1、事件的聲明:
聲明的格式為:<access modifier> event <delegate type> EventName
????????因為使用委托來聲明事件,所以在類里聲明事件時,首先必須先聲明該事件的委托類型<delegate type>(如果尚未聲明的話)。在上面我們已經提到過了委托類型的聲明,但是在.net??framework下為事件使用的委托類型進行聲明時有更嚴格的規定:
(1)、 事件的委托類型應采用兩個參數;
(2)、兩個參數分別是:指示事件源的“對象源”參數和封裝事件的其他任何相關信息的“e”參數;
(3)、“e”參數的類型應為EventArgs 類或派生自 EventArgs 類。
如下的定義:
public delegate void PrintHandler(object sender,System.EventArgs e);
然后我們才能聲明該委托類型的事件
例如:
public event PrintHandler Print;
當事件發生時,將調用其客戶提供給它的委托。
2、調用事件:
????????類聲明了事件以后,可以就像處理所指示的委托類型的字段那樣處理該事件。如果沒有任何客戶將委托與該事件綁定,則該字段將為空;否則該字段引用應在調用該事件時調用的委托。因此,調用事件時通常先檢查是否為空,然后再調用事件。(調用事件,即觸發事件,只能從聲明該事件的類內進行)
if(Print != null)
{
????????????????Print (this,e);
}
3、事件綁定:
????????從類的外面來看,事件就象類的一個公共成員,通過 類名.事件名 的形式來訪問,但是只能對它做綁定和解除綁定的操作,而不能有其他操作。
類名. Print += new PrintHandler(綁定的方法名)??// 將某個方法綁定到Print事件上
類名. Print??-= new PrintHandler(綁定的方法名)??// 將某個已綁定到Print事件上的方法從Print事件上解除
三、委托和事件的使用
委托和事件在用戶界面程序里用的比較的多,比如象在winform或webform的用戶UI上的button和它的click事件:
// 將Button1_Click()方法綁定到按鈕控件Button1的Click事件上
this.Button1.Click += new System.EventHandler(this. Button1_Click);
private void Button1_Click(object sender, System.EventArgs e)????// Button1_Click()方法
{
????????????????……??
}
然而除了用戶界面程序外,在很多其他地方也用到了事件驅動模式,比如觀察者模式(Observer)或發布/訂閱(Publish/Subscribe)里:在一個類里發布(Publish)某個可以被觸發的事件,而其他的類就可以來訂閱(Subscribe)該事件。一旦這個發布者類觸發了該事件,那么運行時環境會立刻告知所有訂閱了該事件的訂閱者類:這個事件發生了!從而各個訂閱者類可以作出它們自己的反應(調用相應方法)。
我們來舉一個生活中的實際例子來說明如何使用委托和事件,以及使用委托和事件所帶來的好處:
比如說有一個公司(場景),你是老板,手下有主管和員工,作為老板你會指派(委托)主管管理員工的工作,如果某個員工玩游戲,則讓某個主管從該員工的薪水里扣去500元錢。
這就是現實中的委托。
而在寫程序中,假設程序員就是老板,有兩個類分別為主管和員工,而主管小王和員工小張就是兩個類的對象實例。員工類有一個方法:玩游戲,同時就有一個玩游戲的事件,他一玩游戲就會激發這個事件。而主管類就是負責處理該事件的,他負責把玩游戲的員工的薪水扣除500。
(一)、首先,我們來看看在非委托的情況下比較常見的一種設計方式(當然這不是唯一的方式,也不是最好的方式,但是很常見):
using System;
namespace CSharpConsole
{
????????????????public class 場景
????????????????{
????????????????????????????????[STAThread]
????????????????????????????????public static void Main(string[] args)
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("場景開始了.");
????????????????????????????????????????????????// 生成主管類的對象實例 小王
????????????????????????????????????????????????主管 小王 = new 主管();
????????????????????????????????????????????????// 生成員工類的對象實例 小張,指定他的主管
????????????????????????????????????????????????員工 小張 = new 員工(小王);
????????????????????????????????
????????????????????????????????????????????????Console.WriteLine("該員工本有的薪水:" + 小張.薪水.ToString());
????????????
????????????????????????????????????????????????// 員工開始玩游戲
????????????????????????????????????????????????小張.玩游戲();
????????????????????????????????????????????????Console.WriteLine("現在該員工還剩下:" +小張.薪水.ToString());
????????????????????????????????
????????????????????????????????????????????????Console.WriteLine("場景結束");
????????????????????????????????????????????????Console.ReadLine();
????????????????????????????????}
????????????????}
????????????????// 負責扣錢的人----主管
????????????????public class 主管
????????????????{
????????????????????????????????public 主管()
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("生成主管");
????????????????????????????????}
????????????????????????????????public void 扣薪水(員工 employee)
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("主管:好小子,上班時間膽敢玩游戲");
????????????????????????????????????????????????Console.WriteLine("主管:看看你小子有多少薪水");
????????????????????????????????
????????????????????????????????????????????????Console.WriteLine("開始扣薪水...");
????????????????????????????????????????????????System.Threading.Thread.Sleep(1000);
????????????????????????????????????????????????employee.薪水 = employee.薪水 - 500;
????????????????????????????????????????????????Console.WriteLine("扣薪水執行完畢.");???????????
????????????????????????????????}
????????????????}
????????????????// 如果玩游戲,則會引發事件
????????????????public class 員工
????????????????{
????????????????????????????????// 保存員工的薪水
????????????????????????????????private int m_Money;
????????????????????????????????// 保存該員工的主管
????????????????????????????????private 主管 m_Manager;
????????????????????????????????public 員工(主管 manager)
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("生成員工.");
????????????????????????????????????????????????m_Manager = manager;??// 通過構造函數,初始化員工的主管。
????????????????????????????????????????????????m_Money = 1000; // 通過構造函數,初始化員工的薪水。
????????????????????????????????}
????????????????????????????????public int 薪水 // 此屬性可以操作員工的薪水 。
????????????????????????????????{
????????????????????????????????????????????????get
????????????????????????????????????????????????{
????????????????????????????????????????????????????????????????return m_Money;
????????????????????????????????????????????????}
????????????????????????????????????????????????set
????????????????????????????????????????????????{
????????????????????????????????????????????????????????????????m_Money = value;
????????????????????????????????????????????????}
????????????????????????????????}
????????????????????????????????public void 玩游戲()
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("員工開始玩游戲了..");
????????????????????????????????????????????????Console.WriteLine("員工:CS真好玩,哈哈哈! 我玩...");
????????????????????????????????????????????????System.Threading.Thread.Sleep(1000);
????????????????????????????????????????????????
????????????????????????????????????????????????m_Manager. 扣薪水(this);
????????????????????????????????}
????????????????}
}
這種方法所帶來的問題: 員工類和主管類的耦合性太高
1、???在客戶程序里必須先創建了主管類之后才能生成員工類,如果在不需要主管類對象而只需員工類對象的地方,為了創建所需的員工類對象實例,你也不得不去先創建一個主管類的對象實例;
2、???如果場景劇本(即客戶程序需求)發生了變化
(1)、現在要讓一個新的角色(一個新的類),如保安,來代替主管,負責在員工玩游戲時扣員工薪水,那么我們不得不去修改員工類,或許還需要修改主管類;
(2)、如果場景劇本增加新的需求,要求員工在玩游戲后,不但要扣薪水,還要在績效上扣分,那么我們也不得不修改員工類。
(二)、利用委托的實現:
下面有個例子:在C# 控制臺應用程序編輯運行成功:
using System;
namespace CSharpConsole
{
????????????????// 定義委托
????????????????public delegate void PlayGameHandler(object sender,System.EventArgs e);
????????????????// 負責扣錢的人----主管
????????????????public class 主管
????????????????{
????????????????????????????????public 主管()
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("生成主管");
????????????????????????????????}
????????????????????????????????public void 扣薪水(object sender,EventArgs e)
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("主管:好小子,上班時間膽敢玩游戲");
????????????????????????????????????????????????Console.WriteLine("主管:看看你小子有多少薪水");
????????????????
????????????????????????????????????????????????員工 employee = (員工)sender;
????????????????
????????????????????????????????????????????????Console.WriteLine("開始扣薪水...");
????????????????????????????????????????????????System.Threading.Thread.Sleep(1000);
????????????????????????????????????????????????employee.薪水 = employee.薪水 - 500;
????????????????????????????????????????????????Console.WriteLine("扣薪水執行完畢.");???????????
????????????????????????????????}
????????????????}
????????????????// 如果玩游戲,則會引發事件
????????????????public class 員工
????????????????{
????????????????????????????????// 先定義一個事件,這個事件表示員工在玩游戲。
????????????????????????????????public event PlayGameHandler PlayGame;
????????????????????????????????// 保存員工薪水的變量
????????????????????????????????private int m_Money;
????????????????????????????????public 員工()
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("生成員工.");
????????????????????????????????????????????????m_Money = 1000; // 構造函數,初始化員工的薪水。
????????????????????????????????}
????????????????????????????????public int 薪水 // 此屬性可以操作員工的薪水 。
????????????????????????????????{
????????????????????????????????????????????????get
????????????????????????????????????????????????{
????????????????????????????????????????????????????????????????return m_Money;
????????????????????????????????????????????????}
????????????????????????????????????????????????set
????????????????????????????????????????????????{
????????????????????????????????????????????????????????????????m_Money = value;
????????????????????????????????????????????????}
????????????????????????????????}
????????????????????????????????public void 玩游戲()
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("員工開始玩游戲了..");
????????????????????????????????????????????????Console.WriteLine("員工:CS真好玩,哈哈哈! 我玩...");
????????????????????????????????????????????????System.Threading.Thread.Sleep(1000);
????????????????????????????????????????????????System.EventArgs e = new EventArgs();
????????????????????????????????????????????????OnPlayGame(e);
????????????????????????????????}
????????????????????????????????protected virtual void OnPlayGame(EventArgs e)
????????????????????????????????{
????????????????????????????????????????????????if(PlayGame != null)
????????????????????????????????????????????????{
????????????????????????????????????????????????????????????????PlayGame(this,e);
????????????????????????????????????????????????}
????????????????????????????????}
????????????????}
????????????????public class 場景
????????????????{
????????????????????????????????[STAThread]
????????????????????????????????public static void Main(string[] args)
????????????????????????????????{
????????????????????????????????????????????????Console.WriteLine("場景開始了.");
????????????????????????????????????????????????// 生成主管類的對象實例 小王
????????????????????????????????????????????????主管 小王 = new 主管();
????????????????????????????????????????????????// 生成員工類的對象實例 小張
????????????????????????????????????????????????員工 小張 = new 員工();
????????????????????????????????????????????????// 設下委托,指定監視
????????????????????????????????????????????????小張.PlayGame += new PlayGameHandler(小王. 扣薪水);
????????????????????????????????
????????????????????????????????????????????????Console.WriteLine("該員工本有的薪水:" + 小張.薪水.ToString());
????????????
????????????????????????????????????????????????// 員工開始玩游戲
????????????????????????????????????????????????小張.玩游戲();
????????????????????????????????????????????????Console.WriteLine("現在該員工還剩下:" +小張.薪水.ToString());
????????????????????????????????
????????????????????????????????????????????????Console.WriteLine("場景結束");
????????????????????????????????????????????????Console.ReadLine();
????????????????????????????????}
????????????????}
}
對于前面提出的問題:
1、???解耦了主管類和員工類之間的必然聯系,可以單獨創建員工類對象實例,而不用管是否有主管類對象實例的存在;
2、???在客戶程序需求變化時:
(1)、我們只需修改客戶程序,即上面例子里的class 場景,將委托改為如下:
保安 小李 = new 保安();
小張.PlayGame += new PlayGameHandler(小李. 扣薪水);
即可實現由保安來負責扣薪水的需求變化,而不用動員工類。
(2)、我們只需修改客戶程序,即上面例子里的class 場景,添加一個如下的委托:
????????????????小張.PlayGame += new PlayGameHandler(某某. 扣績效分);
這個“某某”可以是主管,也可以是其他新的角色(新的類),只需要在“某某”對應的類里定義扣績效分的動作即可,而不用動員工類。
四、總結:
??????當然,不使用委托和事件我們仍然可以設計出解耦的類,然而卻會增加很多的類、接口以及關聯等等,增加了代碼量和程序的邏輯復雜性,而在.net里利用委托和事件我們只需少的多的代碼來實現。
??委托和事件的使用有如下幾個要素:
1、激發事件的對象-----就是員工小張
2、處理對象事件的對象-----就是主管小王
3、定義委托,就是你讓主管小王監視員工小張。
如果這三個要素都滿足的話,則你就寫出了一個完整事件的處理。??
總結
以上是生活随笔為你收集整理的C#里的委托和事件实现 (转)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 未来中国最受宠的人才
- 下一篇: 自己动手构建iSCSI磁盘阵列