Wariancja w interfejsach ogólnych (Visual Basic)

Program .NET Framework 4 wprowadził obsługę wariancji dla kilku istniejących interfejsów ogólnych. Obsługa wariancji umożliwia niejawną konwersję klas implementujących te interfejsy. Następujące interfejsy są teraz wariantami:

Kowariancja zezwala metodzie na bardziej pochodny typ zwracany niż zdefiniowany przez ogólny parametr typu interfejsu. Aby zilustrować funkcję kowariancji, rozważ następujące interfejsy ogólne: IEnumerable(Of Object) i IEnumerable(Of String). Interfejs IEnumerable(Of String) nie dziedziczy interfejsu IEnumerable(Of Object) . Jednak String typ dziedziczy Object typ, a w niektórych przypadkach można przypisać do siebie obiekty tych interfejsów. Jest to pokazane w poniższym przykładzie kodu.

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

We wcześniejszych wersjach programu .NET Framework ten kod powoduje błąd kompilacji w języku Visual Basic za pomocą polecenia Option Strict On. Teraz można jednak użyć wartości strings zamiast objects, jak pokazano w poprzednim przykładzie, ponieważ IEnumerable<T> interfejs jest kowariantny.

Kontrawariancja umożliwia metodzie posiadanie typów argumentów, które są mniej pochodne niż określone przez ogólny parametr interfejsu. Aby zilustrować kontrawariancję, załóżmy, że utworzono klasę BaseComparer do porównywania wystąpień BaseClass klasy. Klasa BaseComparer implementuje interfejs IEqualityComparer(Of BaseClass). IEqualityComparer<T> Ponieważ interfejs jest teraz kontrawariantny, można użyć BaseComparer do porównania wystąpień klas, które dziedziczą klasęBaseClass. Jest to pokazane w poniższym przykładzie kodu.

' 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

Aby uzyskać więcej przykładów, zobacz Using Variance in Interfaces for Generic Collections (Visual Basic) (Używanie wariancji w interfejsach dla kolekcji ogólnych (Visual Basic).

Wariancja w interfejsach ogólnych jest obsługiwana tylko w przypadku typów referencyjnych. Typy wartości nie obsługują wariancji. Na przykład IEnumerable(Of Integer) nie można niejawnie przekonwertować na IEnumerable(Of Object)wartość , ponieważ liczby całkowite są reprezentowane przez typ wartości.

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

Należy również pamiętać, że klasy implementujące interfejsy wariantów są nadal niezmienne. Na przykład chociaż List<T> implementuje kowariantny interfejs IEnumerable<T>, nie można niejawnie przekonwertować List(Of Object) na List(Of String). Jest to pokazane w poniższym przykładzie kodu.

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

Zobacz też