在上一篇博文当中,我们例举了一个机房自动化系统的逻辑控制程序,其中用到了Lambda表达式,因此方便了我们程序功能的实现.然而,我们不能仅仅为实现功能,完成任务而奋斗,应该知其然,知其所以然,也就是说,知道了Lambda表达式能够带来这样的方便,也应该知道为什么能够带来这样的方便,接下来,就跟大家一起来一次小小的探索之旅吧.
为了弄清为什么,我们用Reflector反编译一下源程序,
static void Main(string[] args){Monitor.OpenEventHandler OnOpen;//定义一个委托变量OpenSomething openSomething = new OpenSomething();//实例化用于开启的对象OnOpen = openSomething.OpenPower;OnOpen += openSomething.OpenServer;OnOpen += () => openSomething.OpenServices(5);//依然是把方法的引用赋值给委托变量OnOpen();Console.ReadKey();}}
用Reflector反编译一下,查看Program类的Main方法,如下图
先是实例化一个OpenSomething对象,然后实例化OpenEventHandler类型的委托变量,并将OpenPower方法的引用赋给它,这在源程序中是分两行来完成的,这里因为是反编译,其实道理都一样.
接下来的一行代码,揭示了给委托赋值的原理,也就是我们用的”+=”符号,在反编译之后,可以看到,它其实是调用了Delegate类的Combine方法,该方法的作用是把两个委托连接起来,它有两个参数,参数类型都是委托,第一个是OnOpen,也就是原委托,第二个就是需要连接的另一个委托,new Monitor.OpenEventHandler(openSomething.OpenPower)其实是实例化了一个新的委托变量,并以此来和OnOpen连接。因此,我们得知,在日常使用”+=”时,表面上看起来是将方法名”拼接”到一个委托变量的后面,调用委托时,会依次调用这些方法,而实际上是将两个类型相同的委托变量Combine到一起,原来如此啊……
再接再励,下面的一行代码对应源程序中的Lambda表达式了,它与上一行不同的是,第二个参数用到了delegate{…}语法,这是匿名委托,由此可见,在用Lambda表达式时,内部实现原理其实就是新定义了一个可以传参的匿名委托,这样,我们就明白了,连接类型相同的委托变量时,程序会实例化一个新委托变量,而连接不同类型的委托变量,程序会定义并实例化一个匿名委托,用于连接,而对于委托变量之间的连接,并不要求它们拥有相同的委托类型。
Lambda表达式在一定程度上对以前的技术进行了封装,而至于为什么要封装,以及除封装以外还有的许多其他特性,是值得我们去研究的。我们在学习对自己来说是新的技术的时候,要养成知其所以然的习惯,知道Lambda表达式可以这样用,再经过类似本文这样的探究之后,对它的印象是不是会更深刻呢。了解了它,再用它,才会得心应手,可控性才会强,出问题了,也更容易发现。这就好比在公司,老板要对他的员工委以重任,必须先要了解这个员工的性格,考虑他是否合适做,而不仅仅是看他能力,一样的。