c#中的delegate(委托)和event(事件)
委托: 托付其他人做這件事 ,包括 托付自己 ,即 一個方法 可以 調用 沒有關系的其他方法 , 也可以 將委托傳遞過去 ,回調自己的方法 ,且 可以自定義參數 ,非常方便 互相傳值, 適合解耦 關系。
示例:
public delegate void ChangeMoney(object s, int n); // 用 delegate 聲明委托
1、 調用 其他方法
售賣 頁面添加商品,添加 的 商品 在另一個頁面也能看見 。
售賣頁面 類裏面 定義委托:
//定義一個委托
public delegate void GetProductHander(List<MarkingModel> mlist);
// 將創建的委托和特定事件關聯
public static event GetProductHander getproduct;
//點擊添加商品時 調用 委托方法:
if(點擊添加商品)
{
getproduct.Invoke(_list);
}
另一個頁面調用委托:
ProductSaleMarketing.getproduct += new ProductSaleMarketing.GetProductHander(GetList);
// 將 要調用的 GetList 方法 放到 getproduct (從類裏面點出來)後面。 以及實現 GetList 方法
private void GetList(List<MarkingModel> _mlist)
{
}
2. 相當於回調方法
這個要在類外面定義委托 ,因為 回調 是 在其他頁面實例化委托 ,調用 連接的方法。 誰在後邊 後邊調用誰。
public delegate void ChangeMoney(object s, int n); // 在頁面外邊 聲明委托 其他頁面都可調用
public partial class TiHuoBill : BaseForm
{
//多窗口共用事件
private void sn_EveDelSelectNumber(object cash, int n)
{
ChangePay(cash, n);
}
//現金
private void btnCash_Click(object sender, EventArgs e)
{
var sn = new ShowNumber(7);
sn.CardMoney = _daishou;
sn.EveDelSelectNumber += sn_EveDelSelectNumber; // 主要就是 這句話 委托在ShowNumber 頁面 實例化了, += 即 那個頁面執行後 調用 sn_EveDelSelectNumber
sn.ShowDialog();
}
}
ShowNumber 頁面 :
public ChangeMoney EveDelSelectNumber; // 實例化委托
// 確定關閉頁面的時候
private void btnSure_Click(object sender, EventArgs e)
{
EveDelSelectNumber(SelectMoney, SelectType); // 調用委托 並傳值 或者這種方式: EveDelSelectNumber.Invoke(SelectMoney, SelectType);
}
暫時發現 委托 可以使用這兩種方式
其中 delegate 和 event 效果 是一樣的
區別 :event與delegate的區別
首先,通過加入event關鍵字,在編譯的時候編譯器會自動針對事件生成一個私有的字段(與此事件相關的委托),以及兩個訪問器方法,即add訪問器方法以及remove訪問器方法,用於對事件的註冊及註銷(對事件使用+=及-=操作時就是調用的這兩個方法)。
我想你們的問題主要是,實際上聲明一個委托類型的字段也可以實現這些功能。
實際上之所以采用event而不直接采用委托,實際上還是為了封裝。可以設想一下,如果直接采用公共的委托字段,類型外部就可以對此字段進行直接的操作了,比如將其直接賦值為null。
而使用event關鍵字就可以保證對事件的操作僅限於add訪問器方法以及remove訪問器方法(即只能使用+=及-=)
在Msdn中,有一段話描述Delegate和Event之間的關系,其實很簡單:
聲明事件:若要在類內聲明事件,首先必須聲明該事件的委托類型。
委托還適用於 觀察者模式:
class Program
{
static void Main(string[] args)
{
var car = new Car(15);
new Alerter(car);
car.Run(120);
}
}
class Car
{
public delegate void Notify(int value);
public event Notify notifier;
private int petrol = 0;
public int Petrol
{
get { return petrol; }
set
{
petrol = value;
if (petrol < 10) //當petrol的值小於10時,出發警報
{
if (notifier != null)
{
notifier.Invoke(Petrol);
}
}
}
}
public Car(int petrol)
{
Petrol = petrol;
}
public void Run(int speed)
{
int distance = 0;
while (Petrol > 0)
{
Thread.Sleep(500);
Petrol--;
distance += speed;
Console.WriteLine("Car is running... Distance is " + distance.ToString());
}
}
}
class Alerter
{
public Alerter(Car car)
{
car.notifier += new Car.Notify(NotEnoughPetrol);
}
public void NotEnoughPetrol(int value)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("You only have " + value.ToString() + " gallon petrol left!");
Console.ResetColor();
}
}
看完了上面的代碼後,你可能會問:為什麽不在public int Petrol中直接調用Alerter.NotEnoughPetrol呢?因為Car模塊和Alerter模塊本身是兩個獨立的子系統,如果直接調用,耦合性就會增加,這不是我們願意看到的。
其實以上的代碼是設計模式中的觀察者模式(觀察者模式又稱Source/Listener模式)的實現,當汽車在運行中汽油量<10時,警報器便會發出警報。在上面代碼中,Delegate相當於一個存放回調函數的函數指針,使用Delegate,我們可以非常方便地實現觀察者模式。而其實,在需要使用回調函數時,我們都可以考慮使用Delegate。
不知道你有沒有發現在上面的代碼中還有一個問題呢?
public event Notify notifier;
上面的代碼中,我們定義了一個Event,而事實上:
public Notify notifier;
這樣寫,也完全可以滿足我們的需求,這就引出了我們的另一個問題,Delegate和Event! 如上 有說明。
參考: 談C#中的Delegate
event與delegate的區別
終於會用c#中的delegate(委托)和event(事件)了
c#中的delegate(委托)和event(事件)