Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Sie können generische Typparameter in Schnittstellen als kovariant oder kontravariant deklarieren. Mit der Kovarianz können Schnittstellenmethoden über mehr abgeleitete Rückgabetypen verfügen als die von den generischen Typparametern definierten. Contravariance ermöglicht es Schnittstellenmethoden, Argumenttypen zu haben, die weniger abgeleitet sind als die von den generischen Parametern angegebenen. Eine generische Schnittstelle mit kovarianten oder kontravarianten generischen Typparametern wird als Variante bezeichnet.
Hinweis
.NET Framework 4 hat die Varianzunterstützung für mehrere vorhandene generische Schnittstellen eingeführt. Eine Liste der Variantenschnittstellen in .NET Framework finden Sie unter Variance in Generic Interfaces (Visual Basic).For the list of the variant interfaces in the .NET Framework, see Variance in Generic Interfaces (Visual Basic).
Deklarieren von generischen Variant-Schnittstellen
Sie können varianten generische Schnittstellen mithilfe der Schlüsselwörter in und out für generische Typparameter deklarieren.
Von Bedeutung
ByRef Parameter in Visual Basic können nicht variant sein. Werttypen unterstützen auch keine Varianz.
Sie können eine generische Typparameterkovariant mithilfe des out Schlüsselworts deklarieren. Der kovariante Typ muss die folgenden Bedingungen erfüllen:
Der Typ wird nur als Rückgabetyp von Schnittstellenmethoden verwendet und nicht als Typ von Methodenargumenten verwendet. Dies wird im folgenden Beispiel veranschaulicht, in dem der Typ
Rkovariant deklariert wird.Interface ICovariant(Of Out R) Function GetSomething() As R ' The following statement generates a compiler error. ' Sub SetSomething(ByVal sampleArg As R) End InterfaceEs gibt eine Ausnahme für diese Regel. Wenn Sie über einen kontravarianten generischen Delegaten als Methodenparameter verfügen, können Sie den Typ als generischen Typparameter für den Delegaten verwenden. Dies wird durch den Typ
Rim folgenden Beispiel veranschaulicht. Weitere Informationen finden Sie unter Varianz in Delegaten (Visual Basic) und Using Variance for Func and Action Generic Delegates (Visual Basic).Interface ICovariant(Of Out R) Sub DoSomething(ByVal callback As Action(Of R)) End InterfaceDer Typ wird nicht als generische Einschränkung für die Schnittstellenmethoden verwendet. Dies wird im folgenden Code veranschaulicht.
Interface ICovariant(Of Out R) ' The following statement generates a compiler error ' because you can use only contravariant or invariant types ' in generic constraints. ' Sub DoSomething(Of T As R)() End Interface
Sie können einen generischen Typparameter contravariant mithilfe des Schlüsselworts in deklarieren. Der kontravariante Typ kann nur als Typ von Methodenargumenten und nicht als Rückgabetyp von Schnittstellenmethoden verwendet werden. Der kontravariante Typ kann auch für generische Einschränkungen verwendet werden. Der folgende Code zeigt, wie eine kontravariante Schnittstelle deklariert und eine generische Einschränkung für eine seiner Methoden verwendet wird.
Interface IContravariant(Of In A)
Sub SetSomething(ByVal sampleArg As A)
Sub DoSomething(Of T As A)()
' The following statement generates a compiler error.
' Function GetSomething() As A
End Interface
Es ist auch möglich, sowohl Kovarianz als auch Kontravarianz in derselben Schnittstelle zu unterstützen, aber für verschiedene Typparameter, wie im folgenden Codebeispiel gezeigt.
Interface IVariant(Of Out R, In A)
Function GetSomething() As R
Sub SetSomething(ByVal sampleArg As A)
Function GetSetSomething(ByVal sampleArg As A) As R
End Interface
In Visual Basic können Sie Keine Ereignisse in Variantenschnittstellen deklarieren, ohne den Delegattyp anzugeben. Außerdem kann eine Variantenschnittstelle keine geschachtelten Klassen, Enumerationen oder Strukturen aufweisen, sie kann jedoch geschachtelte Schnittstellen aufweisen. Dies wird im folgenden Code veranschaulicht.
Interface ICovariant(Of Out R)
' The following statement generates a compiler error.
' Event SampleEvent()
' The following statement specifies the delegate type and
' does not generate an error.
Event AnotherEvent As EventHandler
' The following statements generate compiler errors,
' because a variant interface cannot have
' nested enums, classes, or structures.
'Enum SampleEnum : test : End Enum
'Class SampleClass : End Class
'Structure SampleStructure : Dim value As Integer : End Structure
' Variant interfaces can have nested interfaces.
Interface INested : End Interface
End Interface
Implementieren von varianten generischen Schnittstellen
Sie implementieren generische Variantenschnittstellen in Klassen, indem Sie dieselbe Syntax verwenden, die für invariante Schnittstellen verwendet wird. Das folgende Codebeispiel zeigt, wie eine kovariante Schnittstelle in einer generischen Klasse implementiert wird.
Interface ICovariant(Of Out R)
Function GetSomething() As R
End Interface
Class SampleImplementation(Of R)
Implements ICovariant(Of R)
Public Function GetSomething() As R _
Implements ICovariant(Of R).GetSomething
' Some code.
End Function
End Class
Klassen, die Variantenschnittstellen implementieren, sind invariant. Betrachten Sie beispielsweise den folgenden Code.
The interface is covariant.
Dim ibutton As ICovariant(Of Button) =
New SampleImplementation(Of Button)
Dim iobj As ICovariant(Of Object) = ibutton
' The class is invariant.
Dim button As SampleImplementation(Of Button) =
New SampleImplementation(Of Button)
' The following statement generates a compiler error
' because classes are invariant.
' Dim obj As SampleImplementation(Of Object) = button
Erweitern von varianten generischen Schnittstellen
Wenn Sie eine generische Variante-Schnittstelle erweitern, müssen Sie die in und out Schlüsselwörter verwenden, um explizit anzugeben, ob die abgeleitete Schnittstelle Abweichung unterstützt. Der Compiler leitet nicht die Varianz von der Schnittstelle ab, die erweitert wird. Betrachten Sie beispielsweise die folgenden Schnittstellen.
Interface ICovariant(Of Out T)
End Interface
Interface IInvariant(Of T)
Inherits ICovariant(Of T)
End Interface
Interface IExtCovariant(Of Out T)
Inherits ICovariant(Of T)
End Interface
In der Invariant(Of T) Schnittstelle ist der generische Typparameter T invariant, während im IExtCovariant (Of Out T)Typparameter kovariant ist, obwohl beide Schnittstellen dieselbe Schnittstelle erweitern. Die gleiche Regel wird auf kontravariante generische Typparameter angewendet.
Sie können eine Schnittstelle erstellen, die sowohl die Schnittstelle erweitert, bei der der generische Typparameter T kovariant ist, als auch die Schnittstelle, bei der sie kontravariant ist, wenn in der Erweiterungsschnittstelle der generische Typparameter T invariant ist. Dies wird im folgenden Codebeispiel veranschaulicht.
Interface ICovariant(Of Out T)
End Interface
Interface IContravariant(Of In T)
End Interface
Interface IInvariant(Of T)
Inherits ICovariant(Of T), IContravariant(Of T)
End Interface
Wenn jedoch ein generischer Typparameter T in einer Schnittstelle kovariant deklariert wird, können Sie ihn nicht kontravariant in der Erweiterungsschnittstelle oder umgekehrt deklarieren. Dies wird im folgenden Codebeispiel veranschaulicht.
Interface ICovariant(Of Out T)
End Interface
' The following statements generate a compiler error.
' Interface ICoContraVariant(Of In T)
' Inherits ICovariant(Of T)
' End Interface
Vermeiden von Mehrdeutigkeit
Wenn Sie generische Variantenschnittstellen implementieren, kann die Varianz manchmal zu Mehrdeutigkeit führen. Dies sollte vermieden werden.
Wenn Sie z. B. explizit dieselbe generische Variante mit unterschiedlichen generischen Typparametern in einer Klasse implementieren, kann dies mehrdeutig sein. Der Compiler erzeugt in diesem Fall keinen Fehler, aber es wird nicht angegeben, welche Schnittstellenimplementierung zur Laufzeit ausgewählt wird. Dies kann zu subtilen Fehlern in Ihrem Code führen. Betrachten Sie folgendes Codebeispiel.
Hinweis
Visual Basic generiert eine Option Strict OffCompilerwarnung, wenn eine mehrdeutige Schnittstellenimplementierung vorhanden ist. Mit Option Strict On, Visual Basic generiert einen Compilerfehler.
' Simple class hierarchy.
Class Animal
End Class
Class Cat
Inherits Animal
End Class
Class Dog
Inherits Animal
End Class
' This class introduces ambiguity
' because IEnumerable(Of Out T) is covariant.
Class Pets
Implements IEnumerable(Of Cat), IEnumerable(Of Dog)
Public Function GetEnumerator() As IEnumerator(Of Cat) _
Implements IEnumerable(Of Cat).GetEnumerator
Console.WriteLine("Cat")
' Some code.
End Function
Public Function GetEnumerator1() As IEnumerator(Of Dog) _
Implements IEnumerable(Of Dog).GetEnumerator
Console.WriteLine("Dog")
' Some code.
End Function
Public Function GetEnumerator2() As IEnumerator _
Implements IEnumerable.GetEnumerator
' Some code.
End Function
End Class
Sub Main()
Dim pets As IEnumerable(Of Animal) = New Pets()
pets.GetEnumerator()
End Sub
In diesem Beispiel wird nicht festgelegt, wie die pets.GetEnumerator Methode zwischen Cat und Dog auswählt. Dies kann zu Problemen in Ihrem Code führen.