与Microsoft.Net中的string、int一样,delegate首先是一个关键字。通过声明此关键字(delegate),可以定义一个引用类型(
reference type)--或者说,delegate本就是代表一个封装好的类。.Net用它来提供类型安全的回调函数机制。
从一个网上流行的猫鼠联动的例子开始: 老鼠跑,猫叫,主人惊醒。不考虑观察者模式,使用delegate代码如:
小猫Tom( 汤姆)是老鼠Jerry( 杰瑞)的死对头。这天 老鼠Jerry叫来了强壮的老鼠哥哥和老鼠舅舅,要教训下Tom;
运行结果如:
从一个网上流行的猫鼠联动的例子开始: 老鼠跑,猫叫,主人惊醒。不考虑观察者模式,使用delegate代码如:
//注意这个例子是老鼠做为驱动者
//定义一个RunEventHandler委托类型,方法签名为void返回,接受一个mouseName参数.
public delegate void RunEventHandler(string mouseName);
class Mouse
{
public RunEventHandler runEventHandler;
private string _name=string.Empty;
public Mouse(string name)
{
this._name = name;
}
public void Run()
{
if (runEventHandler != null)
runEventHandler(this._name);
}
}
class Cat
{
public void Cry(string mouseName)
{
Console.WriteLine("cat: {0} is running", mouseName);
}
}
class Master
{
public void Say(string mouseName)
{Console.WriteLine("I know {0} is running,shut up!", mouseName);}
}
class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Cat cat = new Cat();
Master master = new Master();
Mouse m1 = new Mouse("Jack");
m1.runEventHandler += new RunEventHandler(cat.Cry);
m1.runEventHandler += new RunEventHandler(master.Say);
m1.Run();
Console.ReadLine();
}
}
这是段运行良好的代码,但为了说明deledate的使用,可以把要求再扩展一下:
小猫Tom( 汤姆)是老鼠Jerry( 杰瑞)的死对头。这天 老鼠Jerry叫来了强壮的老鼠哥哥和老鼠舅舅,要教训下Tom;
Tom听到风声,也邀请了邻居猫Tim助阵,并准备拍下这场战斗。
class MouseFamily
{
//定义Feedback委托类型
public delegate void Feedback(string mouseName, int num);
private string[] mice;
public MouseFamily(string[] mouseName)
{
mice=new string[mouseName.Length];
for (int i = 0; i < mouseName.Length; i++)
mice[i] = mouseName[i];
}
public void Run(Feedback feedback)
{
for (int i = 0; i < mice.Length; i++)
{
if (feedback != null)
feedback(mice[i], i + 1);
}
}
}
class Cat
{
private string _catName;
public Cat(string catName)
{ this._catName = catName; }
public void Cry(string mouseName,int num)
{
Console.WriteLine("{0}:{1} is running,{2}",this._catName,mouseName,num);
Console.WriteLine("Fighting...");
}
}
class Master
{
public void say(string mouseName, int num)
{
Console.WriteLine("Master:I know {0} is running,shup up",mouseName);
}
}
class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
StaticFun();
InstanceFun();
Console.ReadLine();
}
//回调实例对象方法
static void InstanceFun()
{
Program newApp = new Program();
newApp.Fighting();
}
//回调静态方法
static void StaticFun()
{
MouseFamily mouseFamily = new MouseFamily(new string[] { "Jerry", "Jerry's brother", "Jerry'uncle" });
mouseFamily.Run(new MouseFamily.Feedback(Program.Vedio));
}
static void Vedio(string mouseName, int num)
{
Console.WriteLine("Find mouse:{0},{1}", mouseName, num);
}
public void Fighting()
{
MouseFamily mouseFamily = new MouseFamily(new string[] { "Jerry", "Jerry's brother", "Jerry'uncle" });
Cat Tom = new Cat("Tom");
Cat Tim = new Cat("Tim");
Master master = new Master();
mouseFamily.Run(Tom.Cry);
mouseFamily.Run(Tim.Cry);
mouseFamily.Run(master.say);
}
}
运行结果如:
[1]使用delegate的一个特点就是类型安全,即被回调的方法和声明的原形一致,包括返回类型和参数。
这里public delegate void Feedback(string mouseName, int num)和Program.Vedio(...),Cat.Cry(...),Master.say(...)是一致的。
[2]更多的猫或老鼠,或者其他受驱动对象可以方便的添加。
//追加委托对象也可以下面这种方式
//mouseFamily.Run(Tom.Cry);
//mouseFamily.Run(Tim.Cry);
//mouseFamily.Run(master.say);
MouseFamily.Feedback feedback=null;
feedback+=new MouseFamily.Feedback(Tom.Cry);
feedback+=new MouseFamily.Feedback(Tim.Cry);
feedback += new MouseFamily.Feedback(master.say);
mouseFamily.Run(feedback);