Visual Basic 2010 Breaking Changes

The following table lists all the changes that might prevent an application that was created in Visual Basic 2008 from compiling in Visual Basic 2010, or that might change its run-time behavior.

Category

Issue

Description

Array type inference

Inference rules for array initializers have changed.

For example, Dim x() = {1, 2, 3} infers as type Integer.

Dim x() = {1, 2.2, "3"} causes a compiler error when Option Strict is set to On.

In Visual Basic 2008, when you declare an array variable but omit the element type, the compiler assumes the element type to be Object. Visual Basic 2010 introduces inference for array element types, and infers the element type to be the dominant type of the array literal.

If there is no dominant type, type Object is assumed. In this case, if Option Strict is set to On, a compiler error occurs.

For more information, see Arrays in Visual Basic.

Naming conflicts

Types in namespaces imported at the file level take priority over types in namespaces imported at the project level.

If two namespaces each contain a type with the same name, if one type is located in a namespace imported at the project level, and the other type with the same name is located in a namespace imported at the file level, Visual Basic 2010 binds to the type in the namespace imported at the file level. Previous versions bound to the type in the namespace imported at the project level. For more information, see Imports Statement (.NET Namespace and Type).

Query keywords as identifiers

Using a query keyword as an identifier may produce unexpected results.

The Visual Basic compiler accepts keywords as identifier names in various contexts. Because of the new rules for implicit line continuation added in Visual Basic 2010, you may encounter an error if you use a keyword as an element name in a LINQ query that omits line continuation characters.

For example, the following example uses the Aggregate keyword as an identifier name. If the aggregate identifier immediately follows a query, it is considered part of that query because of the implicit line continuation rules for query clauses. In this example, this causes a compiler error.

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

To make sure that a line is not implicitly included in the previous line of code, add an extra line break before the line of code, as shown in the following example.

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

    aggregate += 1

For more information about implicit line continuation, see Statements in Visual Basic.

Modules

Modules are compiled as MustInherit.

Modules are now compiled as MustInherit. This does not affect how modules behave, but it may affect code that uses reflection to examine the types created by the Visual Basic Module statement. For more information, see Module Statement.

Lamdba expressions

Anonymous lambda expressions generate unique types.

The anonymous delegate types generated for lambda expressions are now ensured to be unique. This can affect code that evaluates the types of anonymous delegates for equality, such as the code in the following example.

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())

For more information, see Lambda Expressions (Visual Basic).

Variance in generic interfaces

Ambiguity might be introduced with generic interfaces.

Visual Basic 2010 supports variance (covariance and contravariance) in generic interfaces. You may encounter a warning error regarding ambiguous interfaces when you implement multiple interfaces and one interface is derived from another.

For more information, see Variance in Generic Interfaces (C# and Visual Basic).

Extension methods

Local methods are preferred over extension methods.

If an extension method is defined with the same name and parameters as a method defined for a type, the compiler binds to the local method instead of the extension method. This behavior corrects incorrect binding behavior in Visual Basic 2008. For more information, see Extension Methods (Visual Basic)

Nullable value types

Testing a nullable value type for Nothing by using the = operator produces a compiler warning.

If you test a nullable value type for Nothing by using the = operator, the result is False even if the nullable value type is Nothing, which is most likely not the intended result. Use the Is operator instead, as shown in the following example.

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

Implicit invocation of parameterless functions or properties

If a function or property returns an indexable value such as a string or an array, you can use shortened syntax to refer to an element of the return value by index only if there are no overloads for the function or property.

Consider a parameterless function or property that returns an indexable value, as shown in the following example.

Class Sample

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

End Class

You can use shortened syntax to refer to an element of the return value by index as shown in the following example.

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

Visual Basic 2008 allows this shortened syntax for late-bound calls even if overloads for the function or property exist. In Visual Basic 2010, you can use shortened syntax to refer to an element of the return value by index only if there are no overloads for the function or property.

Class constraints

The Class constraint is no longer assumed.

Visual Basic 2008 infers the Class constraint for a generic parameter if it is constrained by a second generic parameter that is constrained by the Class constraint. Visual Basic 2010 no longer infers that a generic parameter "inherits" the Class constraint. This is because the first generic parameter might be instantiated with a type that implements an interface but is not a class. Interfaces satisfy the Class constraint.

To make sure that a generic parameter is constrained as a class, add the Class constraint as shown in the following example.

    ' 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

For more information, see Generic Types in Visual Basic (Visual Basic).

Partial class methods

If a method that has constrained generic parameters is declared in more than one partial class, all declarations of the method must have identical constraints.

You can declare a method that has generic parameters in more than one partial class. In Visual Basic 2008, the compiler does not always require the constraints on the generic parameters to match for all declarations of the method. Visual Basic 2010 requires that all declarations of the method have identical constraints.

For more information, see Generic Types in Visual Basic (Visual Basic).

Expression trees of lambda expressions

Removed unnecessary boxing of instances of generic parameter types

In Visual Basic 2008, inside an expression tree of a lambda expression, if a generic parameter type is constrained to an interface, invoking a method on an instance of this type always boxes that instance. In Visual Basic 2010, the instance is only boxed when necessary.

For more information about boxing and unboxing, see Visual Basic Language Specification.

Lambda expressions and expression trees

An expression tree of a lambda expression can be returned from an expression tree of a lambda expression.

In Visual Basic 2008, if a lambda expression casts a lambda expression to an expression tree, the compiler does not perform the cast in some cases. The Visual Basic 2010 compiler correctly casts lambda expressions as expression trees if the cast occurs within a lambda expression.

See Also

Concepts

What's New in Visual Basic 2010

Other Resources

Getting Started with Visual Basic