-- Lambda
这个世界上很多东西是没有道理的...不知道你是不是也会这样觉得。
老实说,过去写程序写惯了的人,一开始看到Lambda表达式会觉得怪怪的,我先讲它的意义,官方说法是,Lambda表达式可以简化程序代码的写法、增加可读性(老实说我觉得简化程序代码的写法这件事情很少跟增加可读性可以一起发生,通常程序代码越简化,可读性就越差...),对Lambda表达式来说,简化程序代码写法可能是做到了,增加可读性我就很犹豫了,不过如果真要说起来,Lambda表达式的出现(或是为什么在这个版本出现)其实说穿了还是跟LINQ有关...
先写一个简单的Lambda:
Function(para1 As Integer) para1 + 1
MSDN上说,Lambda表达式是没有名称的函数,所以上面名称不见了,return也不见了,其实你可以想成:
Function 函数名称(para1 As Integer) Return para1 + 1
上面这样的简写,只是把函数名称和teturn拿掉,这样就比较容易懂了。
例如,原本应该写成
'计算身高体重的BMI值
Function BMI(height As Single,weight As Single)
Return weight / ((height / 100) ^ 2)
End Function
就变成(拉成一行)
Function(height As Single, weight As Single) weight / ((height / 100) ^ 2)
对照着写就比较容易理解了,函数名称不见了, 自然End Function也不见了,Return也不见了,差不多这样,就是Lambda表达式了。
注意:另外一个很重要的是,函数写在程序代码区块外面,Lambda表达式则混杂在一般的程序代码里面。(往下看,就会知道意思)
好,定义出来的Lambda表达式怎么用呢?
最简单的方式是在Lambda表达式的外面加上( ), 变成(Lambda表达式)然后再把参数给进去,所以就变成:
(Lambda表达式)(Lambda表达式需要的参数值)
例如:
Dim ret As Single
ret = (Function(height As Single, weight As Single) weight / ((height / 100) ^ 2))(170, 60)
意义是→接收值=(Lambda表达式)(Lambda表达式需要的参数值)
差不多就是这样,但是,这样很难用对不对....对!!!
所以,大多数人就写成这样:
Dim BMI = (Function(height As Single, weight As Single) weight / ((height / 100) ^ 2))
Dim ret As Single
ret = BMI(170, 60)
其中的BMI我们称为委派变量,BMI是一个变量,但是在内存中是一个函数的位置,所以我们可以调用他(传入170, 60)计算出一个BMI值,再用ret这个Single变量去接收,完成,就是这样。
不过问题开始浮现,如果要这样搞,那为何不干脆一开始就直接建立一个BMI函数就算了?干嘛用Lambda建立了一个没有名称的函数,又要用另一个变数去委派呢???
这还是有原因的,原因也还是跟LINQ有关,我们看一段点底下的程序代码:
Function test()
Dim a() As Integer = {1, 2, 3, 4, 5, 6, 7, 8, 9}
Dim b = From item In a Where item > 3
Return False
End Function
其中的变量b的来源值是一段LINQ语法,这段语法会被Compile成:
Public Shared Function test() As Object
Dim a As Integer() = New Integer() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
Dim b As IEnumerable(Of Integer) = Enumerable.Where(Of Integer)(a, New Func(Of Integer, Boolean)(Nothing, DirectCast(Module1._Lambda$__1, IntPtr)))
Return False
End Function
你会注意到,其中就有调用到一段Compile帮你自动产生的Lambda表达式。你会发现,Lambda有大半在这个版本的.NET中会出现的原因跟LINQ有着密不可分的关系。所以你会慢慢了解,为何从很多文件和名家的BLOG当中都这么说,从.NET 2.0之后,其实本质上.NET Framework已经没有太大的改变,而其他的部分.NET 3.0中的WPF, WWF...等,是额外加上去的,迭在原本的架构之上,同样的.NET 3.5当中所提供的LINQ机制,也就是NameSpace位于System.Linq底下的,则是在.NET 3.5当中迭在3.0之上的一块,骨子里都一样,所以为了实现LINQ这样而外加上去的特殊语法,所以增加了Lambda,让你开发的时候可以很轻松的编写 From item In a Where item > 3 这样的语法,再由IDE与Compile通力合作,把要完成的功能隐藏在这段所谓的LINQ语法后面,再通过Lambda和其他的技巧实现,完成现在你看到的伟大工作。