Visual Basic 2010 重大更改

下表列出了可能阻止在 Visual Basic 2010 中创建的应用程序在 Visual Basic 2008 中进行编译,或可能更改该应用程序的运行时行为的所有更改。

类别

问题

说明

数组类型推理

数组初始值设定项的推理规则已更改。

例如,Dim x() = {1, 2, 3} 推理为类型 Integer。

在 Option Strict 设置为 On 时,Dim x() = {1, 2.2, "3"} 会导致编译器错误。

在 Visual Basic 2008 中,如果您声明一个数组变量但忽略元素类型,则编译器假设元素类型为 Object。 Visual Basic 2010 引入对数组元素类型的推理,并将元素类型推理为数组文本的主导类型。

如果没有主导类型,则假定类型 Object。 在这种情况下,如果 Option Strict 设置为 On,则会发生编译器错误。

有关更多信息,请参见 数组 (Visual Basic)

命名冲突

在文件级导入的命名空间中的类型优先于在项目级导入的命名空间中的类型。

如果两个命名空间均包含同名的类型,且如果一个类型位于在项目级导入的命名空间,另一个同名的类型位于在文件级导入的命名空间,则 Visual Basic 2010 将绑定到在文件级导入的命名空间中的类型。 以前的版本将绑定到在项目级导入的命名空间中的类型。 有关更多信息,请参见Imports 语句(.NET 命名空间和类型)

将查询关键字用作标识符

将查询关键字用作标识符可能会产生意外的结果。

Visual Basic 编译器在各种上下文中均接受关键字作为标识符名称。 由于在 Visual Basic 2010 中添加了针对隐式续行符的新规则,因此如果您在忽略行继续符的 LINQ 查询中将关键字用作元素名称,则可能会遇到错误。

例如,下面的示例将 Aggregate 关键字用作标识符名称。 如果 aggregate 标识符紧跟在某查询的后面,则会由于查询子句的隐式续行符规则而将该标识符视为该查询的一部分。 在以下示例中,这会导致编译器错误。

Dim aggregate = 0
Dim numbers = {1, 2, 3, 4, 5}
Dim query As IEnumerable(Of Integer)

While aggregate < 5

    query = From i In numbers
            Skip aggregate
            Take 1
            Select i
    aggregate += 1

End While

为确保某行未隐式包括在上一行代码中,请在该行代码前添加一个附加分行符,如以下示例所示。

    query = From i In numbers
            Skip aggregate
            Take 1
            Select i

    aggregate += 1

有关隐式续行符的更多信息,请参见语句 (Visual Basic)

模块

模块将编译为 MustInherit。

现在,模块将编译为 MustInherit。 这不会影响模块的行为方式,但可能会影响使用反射来检查由 Visual Basic Module 语句所创建类型的代码。 有关更多信息,请参见 Module 语句

Lambda 表达式

匿名 lambda 表达式生成唯一的类型。

为 lambda 表达式生成的匿名委托类型现在确保为唯一类型。 这可能会影响评估匿名委托的类型是否相等的代码,例如下面的示例中的代码。

Dim x = Function(a As Integer) a + 1
Dim y = Function(b As Integer) b + 1

' Returns True in Visual Basic 2008. Returns False in Visual Basic 2010.
Dim t = x.GetType().Equals(y.GetType())

有关更多信息,请参见 Lambda 表达式 (Visual Basic)

泛型接口中的变体

泛型接口可能会引入多义性。

Visual Basic 2010 支持泛型接口中的变体(协变和逆变)。 在您实现多个接口且一个接口派生自另一个接口时,可能会遇到有关接口不明确的警告错误。

有关更多信息,请参见泛型接口中的变体(C# 和 Visual Basic)

扩展方法

本地方法优先于扩展方法。

如果定义扩展方法时使用的名称和参数与为类型定义方法时相同,则编译器将绑定到本地方法,而不是扩展方法。 此行为会更正 Visual Basic 2008 中不正确的绑定行为。 有关更多信息,请参见扩展方法 (Visual Basic)

可以为 null 值的类型

通过使用 = 运算符测试 Nothing 的可以为 null 值的类型(如下面的代码所示)会产生编译器错误。

Dim i? As Integer
If i = Nothing Then
  ' ...
End If

如果通过使用 = 运算符测试 Nothing 的可以为 null 值的类型,则即使可以为 null 值的类型为 Nothing 测试结果也为 False,该结果很可能不是预期结果。 应改用 Is 运算符,如以下示例所示。

Dim i? As Integer
If i Is Nothing Then
  ' ...
End If

无参数函数或属性的隐式调用

如果某函数或属性返回一个可索引的值(例如字符串或数组),则只有在该函数或属性没有重载的情况下,才可以使用短语法按索引来引用返回值的元素。

假定有一个能返回可索引的值的无参数函数或属性,如下面的示例所示。

Class Sample

    Public Function GetValue() As String
        Return "Default Value"
    End Function

End Class

您可以使用短语法按索引来引用返回值的元素,如下面的示例所示。

Dim o As Object = New Sample()
' Returns "D" if no overloads exist for the GetValue function.
Dim val = o.GetValue(0)

即使存在该函数或属性的重载,Visual Basic 2008 也允许此短语法用于后期绑定调用。 在 Visual Basic 2010 中,只有在该函数或属性没有重载的情况下,才可以使用短语法按索引来引用返回值的元素。

Class 约束

不再假设为 Class 约束。

如果某泛型形参受另一个泛型形参的约束,且后者受 Class 约束的约束,则针对前一泛型形参 Visual Basic 2008 会推理出 Class 约束。 Visual Basic 2010 不再推理出泛型形参“继承”Class 约束。 这是因为第一个泛型形参可能使用能实现接口但不是类的类型实例化。 接口满足 Class 约束。

为确保泛型形参被约束为类,请添加 Class 约束,如下面的示例所示。

    ' The following code causes a compiler error.
    ' Function RefEquals(Of T1 As T2, T2 As Class)(ByVal x As T1, ByVal y As T2) As Boolean
    '     Return y Is x
    ' End Function

    ' The following code is valid in Visual Basic 2010.
    Function RefEquals(Of T1 As {T2, Class}, T2 As Class)(ByVal x As T1, ByVal y As T2) As Boolean
        Return y Is x
    End Function

有关更多信息,请参见 Visual Basic 中的泛型类型 (Visual Basic)

分部类方法

如果在多个分部类中声明了已约束泛型形参的方法,则该方法的所有声明均必须具有相同的约束。

可以在多个分部类中声明具有泛型形参的方法。 在 Visual Basic 2008 中,编译器并不始终要求对泛型形参的约束与该方法的所有声明匹配。 Visual Basic 2010 要求该方法的所有声明均具有相同的约束。

有关更多信息,请参见 Visual Basic 中的泛型类型 (Visual Basic)

Lambda 表达式的表达式树

已删除泛型形参类型实例的不必要装箱

在 Visual Basic 2008 中,在 lambda 表达式的表达式树内,如果泛型形参类型被约束为接口,则对该类型的实例调用方法会始终对该实例进行装箱。 在 Visual Basic 2010 中,只有在必要时才会对实例进行装箱。

有关装箱和取消装箱的更多信息,请参见Visual Basic 语言规范

Lambda 表达式和表达式树

可从 lambda 表达式的表达式树中返回 lambda 表达式的表达式树。

在 Visual Basic 2008 中,如果 lambda 表达式将 lambda 表达式强制转换为表达式树,则在某些情况下编译器不执行该强制转换。 如果是在 lambda 表达式中发生强制转换,则 Visual Basic 2010 编译器会正确地将 lambda 表达式强制转换为表达式树。

请参见

概念

Visual Basic 2010 中的新增功能

其他资源

Visual Basic 入门