C#委托(delegate)学习
参考资料
《C#技术揭密》
http://www.microsoft.com/china/msdn/events/featureevents/default.mspx 这里有一些微软.net编程的视频资料
对学过c/c++的来说,delegate就相当于函数指针,看下面的代码:
class Person
{
public Person(string name)
{
this.name=name;
}
//一些属性和方法
string name;
public void Eat(Food food);
}
Person类有一个Eat方法,对它的实例来说,张三,李四,王五都有他们自己的Eat方法
Person zhanSan,liSi,wangWu;
zhanSan=new Person(”张三”);
liSi=new Person(”李四”);
wangWu=new Person(”王五”);
我们可以通过定义一个委托来分别调用Eat方法
public void delegate Eat(Food food);
如果想调用zhanSan.Eat(food)
Eat zhanSanEat=new Eat(zhanSan.Eat);
其他类似:
Eat liSiEat=new Eat(liSi.Eat);
Eat wangWu=new Eat(wangWu.Eat);
这样调用zhanSanEat(food)就相当于调用zhanSan.Eat(food)
委托最有用的是委托链,如果张三,李四,王五共同进餐
则可以定义委托如下
//定义复合委托
Eat togetherEat;
//c#中通过“+“将方法Connect到委托,即将委托加到委托链中
//通过“-”将方法从委托链中删除
togetherEat=zhanSanEat+liSiEat+wangwuEat;
//张三,李四,王五一起吃西瓜
togetherEat(西瓜);
//不带张三,只有李四和王五吃
togetherEat=liSiEat+wangWuEat;
togetherEat(西瓜);
.net中的事件机制就是通过委托来实现的。
下面是C#技术揭密上的一段源代码,我加了一些注释,讲解了事件的实现机制
//InventoryManager类用于更新库存量,它也定义了当更新库存量时应该触发的事件,也就是说它发布一个委托由订阅者调用
//InventoryWatcher类定义的是订阅者,可以选择是否将自己添加到发布者的列表中,从而在更新库存时,得到通知
using System;
namespace DelegateEvents
{
//定义EventArgs的派生类,用来携带事件信息
class InventoryChangeEventArgs:System.EventArgs
{
public InventoryChangeEventArgs(string sku,int change)
{
this.sku=sku;
this.change= change;
}
string sku;
public string Sku
{
get{return sku;}
}
int change;
public int Change
{
get{return change;}
}
}
//发布者
class InventoryManager
{
//声明一个委托,两个参数必不可少,第一个是发布者对象,第二个一定要是EventArgs类或者其派生类
public delegate void InventoryChangeEventHandler(object source,InventoryChangeEventArgs e);
//定义该委托的事件实例(即委托链,用于订阅者将自己加到委托链中
public event InventoryChangeEventHandler OnInventoryChangeHandler;
//InventoryManager的方法,用于更新库存
public void UpdateInventory(string sku,int change)
{
if(0==change)
return;
//定义事件参数实例,传递sku和change信息
InventoryChangeEventArgs e=new InventoryChangeEventArgs(sku,change);
//判断委托链表是否为空,如果不空,说明有订阅者订阅
if(this.OnInventoryChangeHandler!=null)
{
Console.WriteLine("[InventoryManager.UpdateInventory] Raising event to all subscribers...\n");
//依次调用委托链表上的方法
this.OnInventoryChangeHandler(this,e);
}
}
}
//订阅者
class InventoryWatcher
{
//定义发布者
InventoryManager invnetoryManager;
public InventoryWatcher(InventoryManager inventoryManager)
{
Console.WriteLine("[InventoryWatcher.InventoryWatcher] Subscribing to InventoryChange event\n");
this.invnetoryManager=inventoryManager;
//将自己Connect到InventoryManager.InventoryChangeEventHandler委托
inventoryManager.OnInventoryChangeHandler+=new InventoryManager.InventoryChangeEventHandler(OnInventoryChange);
}
//订阅者的方法,用于在发布者更新库存量时调用
void OnInventoryChange(object source,InventoryChangeEventArgs e)
{
int change=e.Change;
Console.WriteLine("[InventoryManager.OnInventoryChange]\n\tPart'{0}' was {1} by {2} units\n",e.Sku,change>0?"increased":"decreased",Math.Abs(e.Change));
}
}
/// <summary>
/// 用委托实现事件机制实例
/// </summary>
class DelegateEvents
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
//定义委托发布者对象
InventoryManager inventoryManager=new InventoryManager();
Console.WriteLine("[DelegateEvents.Main Instantiating subscriber object\n");
//定义订阅者对象
InventoryWatcher inventWatcher=new InventoryWatcher(inventoryManager);
inventoryManager.UpdateInventory("111 006 116",2);
inventoryManager.UpdateInventory("111 005 383",5);
Console.ReadLine();
}
}
}