次の方法で共有


Visual Basic 2010 の互換性に影響する変更点

次の表は、Visual Basic 2008 で作成されたアプリケーションが Visual Basic 2010 でコンパイルされなくなったり、実行時の動作が変わったりする原因となる可能性のある変更の一覧です。

カテゴリ

懸案事項

説明

配列型の推論

配列初期化子の推論規則が変更されています。

たとえば、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 における配列」を参照してください。

名前の競合

ファイル レベルでインポートされた名前空間の型は、プロジェクト レベルでインポートされた名前空間の型より優先されます。

2 つの名前空間にそれぞれ同じ名前の型が含まれており、一方の型がプロジェクト レベルでインポートされた名前空間に、もう一方の型がファイル レベルでインポートされた名前空間に含まれている場合、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 ステートメント」を参照してください。

ラムダ式

匿名ラムダ式では、一意の型が生成されます。

ラムダ式に対して生成される匿名デリゲートの型は、必ず一意になるようになりました。 これは、次の例のコードのように、匿名デリゲートの型の等価性を評価するコードに影響することがあります。

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

詳細については、「ラムダ式 (Visual Basic)」を参照してください。

ジェネリック インターフェイスの変性

ジェネリック インターフェイスであいまいさが生じる可能性があります。

Visual Basic 2010 では、ジェネリック インターフェイスにおける変性 (共変性と反変性) がサポートされています。 複数のインターフェイスを実装し、あるインターフェイスが別のインターフェイスから派生する場合、あいまいなインターフェイスに関する警告エラーが発生することがあります。

詳細については、「ジェネリック インターフェイスの分散 (C# および Visual Basic)」を参照してください。

拡張メソッド

拡張メソッドよりもローカル メソッドが優先されます。

型に対して定義されているメソッドと同じ名前とパラメーターを持つ拡張メソッドを定義しても、コンパイラは、拡張メソッドではなくローカル メソッドにバインドします。 この動作によって、Visual Basic 2008 の不適切なバインディング動作が修正されます。 詳細については、「拡張メソッド (Visual Basic)」を参照してください。

null 許容値型

次のコードに示すように、= 演算子を使用して null 許容値型が Nothing かどうかをテストすると、コンパイラ エラーが生成されます。

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

= 演算子を使用して null 許容値型が Nothing かどうかをテストすると、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 制約は想定されなくなりました。

Visual Basic 2008 では、1 つのジェネリック パラメーターが、Class 制約によって制約されているもう 1 つのジェネリック パラメーターによって制約される場合、最初のジェネリック パラメーターに対して 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)」を参照してください。

ラムダ式の式ツリー

ジェネリック パラメーター型のインスタンスの不必要なボックス化が行われなくなりました。

Visual Basic 2008 のラムダ式の式ツリー内では、ジェネリック パラメーター型がインターフェイスに制約される場合、この型のインスタンスのメソッドを呼び出すと、常にそのインスタンスがボックス化されます。 Visual Basic 2010 では、インスタンスは必要な場合にのみボックス化されます。

ボックス化とボックス化解除の詳細については、「Visual Basic 言語仕様」を参照してください。

ラムダ式と式ツリー

ラムダ式の式ツリーからラムダ式の式ツリーを返すことができます。

Visual Basic 2008 では、ラムダ式でラムダ式を式ツリーにキャストした場合に、コンパライラがそのキャストを実行しないことがあります。 Visual Basic 2010 コンパイラでは、ラムダ式内でキャストが発生した場合、ラムダ式は式ツリーとして正常にキャストされます。

参照

概念

Visual Basic 2010 の新機能

その他の技術情報

Visual Basic の概要