Rozptyl v obecných rozhraních (Visual Basic)
Rozhraní .NET Framework 4 zavedlo podporu odchylek pro několik existujících obecných rozhraní. Podpora rozptylu umožňuje implicitní převod tříd, které implementují tato rozhraní. Nyní jsou variantou následující rozhraní:
IEnumerable<T> (T je kovariantní)
IEnumerator<T> (T je kovariantní)
IQueryable<T> (T je kovariantní)
IGrouping<TKey,TElement> (
TKey
aTElement
jsou kovariantní)IComparer<T> (T je kontravariantní)
IEqualityComparer<T> (T je kontravariantní)
IComparable<T> (T je kontravariantní)
Kovariance umožňuje metodě mít odvozenější návratový typ, než který definuje parametr obecného typu rozhraní. Chcete-li ilustrovat kovarianci funkce, zvažte tato obecná rozhraní: IEnumerable(Of Object)
a IEnumerable(Of String)
. Rozhraní IEnumerable(Of String)
nedědí IEnumerable(Of Object)
rozhraní. String
Typ však zdědí Object
typ a v některých případech můžete chtít přiřadit objekty těchto rozhraní k sobě navzájem. To je znázorněno v následujícím příkladu kódu.
Dim strings As IEnumerable(Of String) = New List(Of String)
Dim objects As IEnumerable(Of Object) = strings
V dřívějších verzích rozhraní .NET Framework tento kód způsobí chybu kompilace v jazyce Visual Basic s Option Strict On
. Nyní ale můžete místo strings
objects
, jak je znázorněno v předchozím příkladu, protože IEnumerable<T> rozhraní je kovariantní.
Kontravariance umožňuje metodě mít typy argumentů, které jsou méně odvozeny, než které specifikuje obecný parametr rozhraní. Chcete-li ilustrovat kontravariance, předpokládejme, že jste vytvořili BaseComparer
třídu pro porovnání instancí BaseClass
třídy. Třída BaseComparer
implementuje rozhraní IEqualityComparer(Of BaseClass)
. Vzhledem k tomu, že IEqualityComparer<T> rozhraní je nyní kontravariantní, můžete použít BaseComparer
k porovnání instancí tříd, které dědí BaseClass
třídu. To je znázorněno v následujícím příkladu kódu.
' 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
Další příklady naleznete v tématu Použití rozptylu v rozhraních pro obecné kolekce (Visual Basic).
Variance v obecných rozhraních je podporována pouze pro odkazové typy. Typy hodnot nepodporují odchylku. Například IEnumerable(Of Integer)
nelze implicitně převést na IEnumerable(Of Object)
, protože celá čísla jsou reprezentována typem hodnoty.
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
Je také důležité si uvědomit, že třídy, které implementují variantní rozhraní, jsou stále invariantní. Ačkoli například List<T> implementuje kovariantní rozhraní IEnumerable<T>, nelze implicitně převést List(Of Object)
na List(Of String)
. To je znázorněno v následujícím příkladu kódu.
' 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)