次の方法で共有


ジェネリック インターフェイスの分散 (Visual Basic)

.NET Framework 4 では、複数の既存のジェネリック インターフェイスに差異のサポートが導入されました。 分散のサポートにより、これらのインターフェイスを実装するクラスの暗黙的な変換が可能になります。 次のインターフェイスがバリアントになりました。

共分散により、メソッドは、インターフェイスのジェネリック型パラメーターで定義された戻り値よりも派生した戻り値の型を持つことができます。 共分散機能を説明するには、 IEnumerable(Of Object)IEnumerable(Of String)の一般的なインターフェイスを検討してください。 IEnumerable(Of String) インターフェイスは、IEnumerable(Of Object) インターフェイスを継承しません。 ただし、 String 型は Object 型を継承します。場合によっては、これらのインターフェイスのオブジェクトを相互に割り当てることができます。 これは次のコードに示されています。

Dim strings As IEnumerable(Of String) = New List(Of String)
Dim objects As IEnumerable(Of Object) = strings

以前のバージョンの .NET Framework では、このコードにより、 Option Strict Onを使用して Visual Basic でコンパイル エラーが発生します。 ただし、前の例に示すように、stringsではなくobjectsを使用できるようになりました。これは、IEnumerable<T> インターフェイスが共変であるためです。

反変性により、メソッドは、インターフェイスのジェネリック パラメーターで指定されたよりも派生度の低い引数型を持つことができます。 反変性を示すために、BaseComparer クラスのインスタンスを比較するBaseClass クラスが作成されていることを前提としています。 BaseComparer クラスは IEqualityComparer(Of BaseClass) インターフェイスを実装しています。 IEqualityComparer<T> インターフェイスは反変であるため、BaseComparerを使用して、BaseClass クラスを継承するクラスのインスタンスを比較できます。 これは次のコードに示されています。

' Simple hierarchy of classes.
Class BaseClass
End Class

Class DerivedClass
    Inherits BaseClass
End Class

' Comparer class.
Class BaseComparer
    Implements IEqualityComparer(Of BaseClass)

    Public Function Equals1(ByVal x As BaseClass,
                            ByVal y As BaseClass) As Boolean _
                            Implements IEqualityComparer(Of BaseClass).Equals
        Return (x.Equals(y))
    End Function

    Public Function GetHashCode1(ByVal obj As BaseClass) As Integer _
        Implements IEqualityComparer(Of BaseClass).GetHashCode
        Return obj.GetHashCode
    End Function
End Class
Sub Test()
    Dim baseComparer As IEqualityComparer(Of BaseClass) = New BaseComparer
    ' Implicit conversion of IEqualityComparer(Of BaseClass) to
    ' IEqualityComparer(Of DerivedClass).
    Dim childComparer As IEqualityComparer(Of DerivedClass) = baseComparer
End Sub

その他の例については、「 ジェネリック コレクションのインターフェイスでの分散の使用 (Visual Basic)」を参照してください。

ジェネリック インターフェイスの差異は、参照型でのみサポートされます。 値型は分散をサポートしていません。 たとえば、整数は値型で表されるため、 IEnumerable(Of Integer) を暗黙的に IEnumerable(Of Object)に変換することはできません。

Dim integers As IEnumerable(Of Integer) = New List(Of Integer)
' The following statement generates a compiler error
' with Option Strict On, because Integer is a value type.
' Dim objects As IEnumerable(Of Object) = integers

また、バリアント インターフェイスを実装するクラスは不変であることにも注意してください。 たとえば、 List<T> は共変インターフェイス IEnumerable<T>を実装しますが、 List(Of Object)List(Of String)に暗黙的に変換することはできません。 これを次のコード例に示します。

' The following statement generates a compiler error
' because classes are invariant.
' Dim list As List(Of Object) = New List(Of String)

' You can use the interface object instead.
Dim listObjects As IEnumerable(Of Object) = New List(Of String)

こちらも参照ください