Afwijking in algemene interfaces (Visual Basic)
.NET Framework 4 heeft variantieondersteuning geïntroduceerd voor verschillende bestaande algemene interfaces. Variantieondersteuning maakt impliciete conversie mogelijk van klassen die deze interfaces implementeren. De volgende interfaces zijn nu variant:
IEnumerable<T> (T is covariant)
IEnumerator<T> (T is covariant)
IQueryable<T> (T is covariant)
IGrouping<TKey,TElement> (
TKey
enTElement
zijn covariant)IComparer<T> (T is contravariant)
IEqualityComparer<T> (T is contravariant)
IComparable<T> (T is contravariant)
Met covariantie kan een methode een meer afgeleid retourtype hebben dan dat is gedefinieerd door de algemene typeparameter van de interface. Als u de covariantiefunctie wilt illustreren, kunt u de volgende algemene interfaces overwegen: IEnumerable(Of Object)
en IEnumerable(Of String)
. De IEnumerable(Of String)
interface neemt de IEnumerable(Of Object)
interface niet over. Het String
type neemt echter het Object
type over en in sommige gevallen wilt u mogelijk objecten van deze interfaces aan elkaar toewijzen. Dit wordt weergegeven in het volgende codevoorbeeld.
Dim strings As IEnumerable(Of String) = New List(Of String)
Dim objects As IEnumerable(Of Object) = strings
In eerdere versies van .NET Framework veroorzaakt deze code een compilatiefout in Visual Basic met Option Strict On
. Maar nu kunt u in plaats van objects
, zoals wordt weergegeven in het vorige voorbeeld, omdat strings
de IEnumerable<T> interface covariant is.
Met contravariantie kan een methode argumenttypen hebben die minder zijn afgeleid dan die zijn opgegeven door de algemene parameter van de interface. Als u de contravariantie wilt illustreren, gaat u ervan uit dat u een BaseComparer
klasse hebt gemaakt om exemplaren van de BaseClass
klasse te vergelijken. Met de klasse BaseComparer
wordt de IEqualityComparer(Of BaseClass)
-interface geïmplementeerd. Omdat de IEqualityComparer<T> interface nu contravariant is, kunt u exemplaren BaseComparer
van klassen vergelijken die de BaseClass
klasse overnemen. Dit wordt weergegeven in het volgende codevoorbeeld.
' 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
Zie Variantie gebruiken in interfaces voor algemene verzamelingen (Visual Basic) voor meer voorbeelden.
Variantie in algemene interfaces wordt alleen ondersteund voor referentietypen. Waardetypen bieden geen ondersteuning voor variantie. Kan bijvoorbeeld IEnumerable(Of Integer)
niet impliciet worden geconverteerd naar IEnumerable(Of Object)
, omdat gehele getallen worden vertegenwoordigd door een waardetype.
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
Het is ook belangrijk te onthouden dat klassen die variantinterfaces implementeren, nog steeds invariant zijn. Hoewel de covariant-interface IEnumerable<T>bijvoorbeeld List<T> wordt geïmplementeerd, kunt u niet impliciet converteren List(Of Object)
naar List(Of String)
. Dit wordt geïllustreerd in het volgende codevoorbeeld.
' 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)