- ·上一篇文章:在VB2005中使用零长度数组
- ·下一篇文章:VB中实现远程数据库的访问
Visual Basic 2010 新增功能
Dim query = Array.FindAll(customers, AddressOf Filter)
...
Function Filter(ByVal c As customer) As Boolean
Return c.Country = "Canada"
End Function
不幸的是,Visual Basic 2008 的 lambda 表达式要求表达式返回值,因此以下代码:
Array.ForEach(customers, Function(c) Console.WriteLine(c.Country))
将会导致以下情况:
'Compile error: "Expression does not produce a value."
Console.WriteLine 是一个 Sub 过程(C# 中为 void),因此它不会返回值,而这就是编译器产生错误的原因所在。为了处理此情况,Visual Basic 2010 引入了对语句 lambda 的支持,后者是包含一个或多个语句的 lambda:
Array.ForEach(customers, Sub(c) Console.WriteLine(c.Country))
由于 Console.WriteLine 不返回值,因此我们可以只创建 Sub lambda,而不是 Function lambda。下面是使用多个语句的另一个示例:
Array.ForEach(customers, Sub(c)
Console.WriteLine("Country Name:")
Console.WriteLine(c.Country)
End Sub)
当此代码运行时,它将为每个客户打印两行。另外请注意,如果在编码时悬停在 c 上,您将看到编译器会将类型推断为 Customer(键入 c As Customer 来显式声明类型也是合法的)。动态编写事件处理程序是语句 lambda 的另一个出色用途:
AddHandler b.Click, Sub(sender As Object, e As EventArgs)
MsgBox("Button Clicked")
'insert more complex logic here
End Sub
并且,事实上,您可以将语句 lambda 与 Visual Basic 2008 中引入的一项功能(松散委托)结合使用。(可以使用委托 – 类型安全的函数指针 – 一次性执行多个函数。)这种组合将生成更为简单的签名:
AddHandler b.Click, Sub()
MsgBox("Button Clicked")
'insert more complex logic here
End Sub
委托松散使您可以完全忽略事件处理程序中的参数 – 这是一个很好的优点,只要它们根本未使用过,因此它们只会在视觉上带来干扰。
除了到目前为止我们已看到的单行 Sub lambda 和多行 Sub lambda 外,Visual Basic 2010 还支持多行 Function lambda:
Dim query = customers.Where(Function(c)
'Return only customers that have not been saved
'insert more complex logic here
Return c.ID = -1
End Function)
语句 lambda 的另一个引人关注的方面是它们与 Visual Basic 2008 引入的匿名委托的相交方式。人们经常将这些委托与 C# 的匿名方法混淆,尽管严ge来说它们并不相同。当 Visual Basic 编译器基于 lambda 的方法签名推断委托类型时,将发生匿名委托:
Dim method = Function(product As String)
If product = "Paper" Then
Return 4.5 'units in stock
Else
Return 10 '10 of everything else
End If
End Function
MsgBox(method("Paper"))
如果运行此代码,您将看到消息框中显示值 4.5。此外,如果悬停在 method 上,您将看到文本 Dim method As <Function(String) As Double>。由于我们未提供实际委托类型,因此编译器将自动生成一个委托类型,如下所示:
Delegate Function $compilerGeneratedName$(product As String) As Double
这称为匿名委托,因为它只会出现在编译器生成的代码中,而不会出现在编写的代码中。请注意,当事实上没有提供 As 子句来指定 lambda 的返回类型时,编译器将返回类型推断为 Double。编译器将查看 lambda 内的所有返回语句,并将确定类型 Double (4.5) 和 Integer (10):
'Notice the "As Single"
Dim method = Function(product As String) As Single
If product = "Paper" Then
Return 4.5 'units in stock
Else
Return 10 '10 of everything else
End If
End Function
然后,它将运行其基准类型算法,并确定它能够安全地将 10 转换为 Double,但无法安全地将 4.5 转换为 Integer;因此 Double 是更好的选择。
您也可以显式控制返回类型,在这种情况下,编译器将不会尝试推断类型。非常常见的做法是将 lambda 赋给具有显式委托类型的变量,而不是依赖于编译器来推断委托类型:
Dim method As Func(Of String, Single) =
Function(product)
If product = "Paper" Then
Return 4.5 'units in stock
Else
Return 10 '10 of everything else
End If
End Function
由于提供了显式目标类型,因此无需声明 As String 或 As Single;编译器可基于语句左边的委托类型来推断出其存在。因此,如果您悬停在 product 上,将会发现推断出的类型为 String。不再必须指定 As Single,因为委托类型已提供该信息。在前面的示例中,Func 委托(.NET Framework 包括该委托)的签名如下所示:
Delegate Function Func(Of T, R)(ByVal param As T) As R
但有一个很小的例外之处,稍后我们将在“泛型方差”一节中看到。
自动实现的属性
在 Visual Basic 中,属性是用于向外部公开对象状态的类成员。典型的属性声明与如下声明类似:
Private _Country As String
Property Country As String
Get
Return _Country
End Get
Set(ByVal value As String)
_Country = value
End Set
End Property
一个实际
Visual Basic 2010 新增功能