一、委托:
委托给我的感觉就是一个种类型,可以让方法更具面向对象的特性——你看,其实我也没说明白,因为我也不大理解。还是一步步往下学吧。
具体来说,委托就是一个类似下面的这种东西:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; namespace ConsoleTestCsharp { class Program { delegate double ProcessDelegate(double param1, double param2); static double Multiply(double param1, double param2) { return param1 * param2; } static double Divide(double param1, double param2) { return param1 / param2; } static void Main(string[] args) { ProcessDelegate process; string input = "M"; if (input == "M") process = new ProcessDelegate(Multiply); else process = new ProcessDelegate(Divide); Console.WriteLine("Result: {0}", process(2, 3)); } } }
给我的感觉反正就是很吊的样子,delegate定义了一个委托类型,注意是类型不是对象,就像class关键字定义了一个类型一样。这个类型将来需要new来进行实例化——这也类似于class。实例化的过程还需要给其传递一个方法。貌似,委托其实定义了一种方法范式:方法接受的参数是什么样子,返回类型是什么样子。至于方法可以做什么动作、完成什么功能,委托类型并不关心,只要你这个方法跟我这个委托类型的方法外观长得一样,你将来就可以实例化我。一旦我——委托类型得到实例化了,我就可以像方法一样被调用了。基本就是这样了,更深刻的理解我也没有。
二、事件:
订阅事件——妈的,关于事件,似乎只在C#里听到订阅这种说法,牛逼哄哄的,让我这种菜鸟又得接受一个新词汇,订阅的意思就是:“订阅一个事件的含义是提供代码,在事件发生时执行这些代码,它们称为事件处理程序。”引号引着,因为这是书中原话。
一个事件可以有多个处理程序——即被多次订阅,事件发生时这些代码都会依次执行。处理程序,就是那个处理函数应该长什么样子——参数是什么,返回类型是什么——由事件相关的委托决定。事件相关的委托是什么毛意思呢,我也不明白,先往下看吧。
class Program { static int counter = 0; static string displayString = "This string will appear one letter at a time. "; static void Main(string[] args) { Timer myTimer = new Timer(100); myTimer.Elapsed += WriteChar; myTimer.Start(); Console.ReadKey(); } static void WriteChar(object source, ElapsedEventArgs e) { Console.Write(displayString[counter++ % displayString.Length]); } }
代码定义了一个Timer,每隔100毫秒触发一次Elapsed事件。然后你搞一个方法处理这个事件(订阅事件),事件发生时调用你的方法,你方法到底应该长什么样子才符合其要求呢。不妨看下Elapsed到底是什么东西。按F12,你会发现在Timer类里,有这样一行:
public event ElapsedEventHandler Elapsed;
接着F12,会发现在System.Timers命名空间里有这样一行:
public delegate void ElapsedEventHandler(object sender, ElapsedEventArgs e);
要知道,ElapsedEventHandler是一种类型,它是直接定义在命名空间里的,而Elapsed则是作为Timer的类成员定义的,是ElapsedEventHandler这种类型的一个实例(严格说来是一个引用)。所以,Elapsed其实是一个委托对象,不过由于它又是用event来限定的,所以跟上边说的委托又不太一样,至于底层到底是什么关系,我是没能力往下挖掘了。反正,可以确定的是:ElapsedEventHandler是一个委托类型无疑,当年这个委托类型是怎么定义的,以后你在订阅这个事件的时候就该,也只能传递某些格式的方法。显然WriteChar是这个符合要求的:
static void WriteChar(object source, ElapsedEventArgs e)
{
Console.Write(displayString[counter++ % displayString.Length]);
}
其实添加一个事件处理程序(订阅)最正宗的做法应该是这样:
myTimer.Elapsed += new ElapsedEventHandler(WriteChar);
可读性要强一点。上面这行代码更加巩固了我的感觉:事件其实就是一个委托实例,订阅事件就是在给这个实例赋值为相应的委托实例。当然,委托类型本身的定义则规定了你在new一个委托的时候应该传递什么样子的方法。妈的,感觉微软的事件机制真有些脱裤子放屁的感觉,我作为一个菜鸟说这些气话也理所当然,因为我还没有体会到大师们作此设计的意义所在,等以后体会到了,再回来道个歉——如果我还记得的话。
三、自定义事件(以后再说,估计短期内也用不到)
四、匿名方法:
匿名方法的目的就是为了简化委托的实例化方式:
myConnection1.MessageArrived +=
delegate(Connection source, MessageArrivedEventArgs e)
{
Console.WriteLine("Message arrived from: {0}", source.Name);
Console.WriteLine("Message Text: {0}", e.Message);
};
C#学习:委托、事件、匿名方法