以下是个人粗浅的理解:
委托delegrate,可以看做是将方法的封装成类型的工具。如(代码摘自http://www.cnblogs.com/firstyi/archive/2008/02/01/1060923.html):
class DelegateTest
{
delegate string Convert(string text);
public void Test()
{
string strText = "123451234512345";
Test2(ConvertA, strText);
Test2(ConvertB, strText);
Test2(ConvertC, strText);
Console.ReadLine();
}
private void Test2(Convert convert, string strText)
{
Console.WriteLine(convert(strText));
}
public string ConvertA(string strText)
{
return strText.Replace("1", "A");
}
public string ConvertB(string strText)
{
return strText.Replace("1", "B");
}
public string ConvertC(string strText)
{
return strText.Replace("1", "C");
}
}
以上代码中定义了一个delegrate,该委托将类似 string method(string str)的方法封装成一个类型Convert(其中method表示方法名)。该类型可以作为参数传递给Test2(Convert convert,string str),其中Convert表示类型,convert 表示变量,于是就可以像一般的方法那样调用了,如Test2(ConvertA,strText),ConvertA 是一个方法,同时也是Convert类型的变量。同时,也可以定义匿名方法,如
class DelegateTest { delegate string Convert(string text); public void Test() { string strText = "123451234512345"; Test2(delegate(string strText2) { return strText2.Replace("1", "A"); }, strText); Test2(delegate(string strText2) { return strText2.Replace("1", "B"); }, strText); Test2(delegate(string strText2) { return strText2.Replace("1", "C"); }, strText); Console.ReadLine(); } private void Test2(Convert convert, string strText) { Console.WriteLine(convert(strText)); } }
代码中专门定义ConverA,ConvertB ConvertC等方法,直接用一个delegrate代替,其实质是一样的。
事件
事件可以理解为封装了委托的属性,让我们在类的外部不对对委托任意操作,只能用“+=”或者“-=“等,要触发事件,可以在类的内部定义一个public方法来触发事件,其实也就是调用方法。没有委托也就没有事件,事件的类型也就是委托所定义的类型,可以把委托所定义的类型的变量,也就是具体方法赋值给事件。
如下
DelegrateTest delegrateTest = new DelegrateTest();
while (true)
{
Console.WriteLine("Input the string ");
string str = Console.ReadLine();
if (str.Contains('1'))
{
delegrateTest.eventConvert +=new DelegrateTest.Convert(delegrateTest.ConvertA);
delegrateTest.OnEventConvert(str);
}
if (str.Contains('2'))
{
delegrateTest.eventConvert += delegrateTest.ConvertB;//这一句同上面delegrateTest.eventConvert +=new DelegrateTest.Convert(delegrateTest.ConvertA)一样,只不过上面使用了委托的初始化函数;
delegrateTest.OnEventConvert(str);
}
if (str.Contains('3'))
{
delegrateTest.eventConvert += delegrateTest.ConvertC;
delegrateTest.OnEventConvert(str);
}
}
在类的外部不能直接触发事件,只能通过delegrateTest的内部方法OnEventConvert()来触发事件。DelegrateTest类如下
class DelegrateTest { public delegate string Convert(string str); public event Convert eventConvert; public string ConvertA(string str) { return str.Replace('1', 'A'); } public string ConvertB(string str) { return str.Replace('2', 'B'); } public string ConvertC(string str) { return str.Replace('3', 'C'); } public void Test(Convert convert, string str) { Console.WriteLine(convert(str)); } public void OnEventConvert(string str) { if(this.eventConvert!=null) { Console.WriteLine( eventConvert(str)); } } }
说的这里,很多人会觉得奇怪,为什么我们在.Net中使用的事件不是这样的呢?主要在于.Net对事件有如下规定(摘自http://www.cnblogs.com/jimmyzhang/archive/2007/09/23/903360.html Jimmy Zhang 的博客,写的简单易懂,大家可以去看一下)
- 委托类型的名称都应该以EventHandler结束。
- 委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。
- 事件的命名为 委托去掉 EventHandler之后剩余的部分。
- 继承自EventArgs的类型应该以EventArgs结尾。
将上面的代码规范化
class Program { static void Main(string[] args) { DelegrateTest delegrateTest = new DelegrateTest(); while (true) { Console.WriteLine("Input the string "); string str = Console.ReadLine(); if (str.Contains('1')) { delegrateTest.eventConvert += new DelegrateTest.Convert(delegrateTest.ConvertA); delegrateTest.OnEventConvert(delegrateTest,new ConvertEventArgs(str)); } if (str.Contains('2')) { delegrateTest.eventConvert += delegrateTest.ConvertB; delegrateTest.OnEventConvert(delegrateTest,new ConvertEventArgs(str)); } if (str.Contains('3')) { delegrateTest.eventConvert += delegrateTest.ConvertC; delegrateTest.OnEventConvert(delegrateTest,new ConvertEventArgs(str)); } } //Timer timer = new Timer(1000); ////下面两句 的效果是一样的,只不过第一句使用了时间的初始化函数初始化了一个方法 //timer.Elapsed += new System.Timers.ElapsedEventHandler(ShowTime); //timer.Elapsed += ShowTime; //timer.Start(); //Console.ReadLine(); } //static void ShowTime(object sender,EventArgs e) //{ // Console.Clear(); // Console.WriteLine(DateTime.Now.ToString("yyyy年MM月dd日 hh:mm:ss")); //} class ConvertEventArgs : EventArgs { public string str; public ConvertEventArgs( string s) { str = s; } } class DelegrateTest { public delegate void Convert(object sender, ConvertEventArgs str); public event Convert eventConvert; public void ConvertA(object sender,ConvertEventArgs e) { Console.WriteLine(e.str.Replace('1', 'A')); } public void ConvertB(object sender,ConvertEventArgs e) { Console.WriteLine(e.str.Replace('2', 'B')); } public void ConvertC(object sender, ConvertEventArgs e) { Console.WriteLine(e.str.Replace('3', 'C')); } //public void Test(Convert convert, string str) //{ // Console.WriteLine(convert(this,new)); //} public void OnEventConvert(object sender, ConvertEventArgs e) { if(this.eventConvert!=null) { eventConvert(sender, e); } } } }
因为我们要传递参数,所以ConvertEventArgs类,该类继承了EventArgs基类,如果不用传递参数,则上面的ConvertEventArgs可以用EventArgs代替。
以上是我自己对委托和事件的粗浅看法。