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.
Mit .NET Framework 3.5 wurde Unterstützung von Varianz eingeführt, um Methodensignaturen und Delegattypen in allen Delegaten in C# und Visual Basic vergleichen zu können. Dies bedeutet, dass Sie Stellvertretungen nicht nur Methoden mit übereinstimmenden Signaturen zuweisen können, sondern auch Methoden, die mehr abgeleitete Typen (Kovarianz) zurückgeben oder Parameter akzeptieren, die weniger abgeleitete Typen (Kontravarianz) als die vom Delegattyp angegeben haben. Dies umfasst sowohl generische als auch nicht generische Delegaten.
Betrachten Sie beispielsweise den folgenden Code mit zwei Klassen und zwei Delegaten: generisch und nicht generisch.
Public Class First
End Class
Public Class Second
Inherits First
End Class
Public Delegate Function SampleDelegate(ByVal a As Second) As First
Public Delegate Function SampleGenericDelegate(Of A, R)(ByVal a As A) As R
Wenn Sie Delegaten der Typen SampleDelegate oder SampleDelegate(Of A, R) erstellen, können Sie diesen Delegaten eine der folgenden Methoden zuweisen.
' Matching signature.
Public Shared Function ASecondRFirst(
ByVal second As Second) As First
Return New First()
End Function
' The return type is more derived.
Public Shared Function ASecondRSecond(
ByVal second As Second) As Second
Return New Second()
End Function
' The argument type is less derived.
Public Shared Function AFirstRFirst(
ByVal first As First) As First
Return New First()
End Function
' The return type is more derived
' and the argument type is less derived.
Public Shared Function AFirstRSecond(
ByVal first As First) As Second
Return New Second()
End Function
Im folgenden Codebeispiel wird die implizite Konvertierung zwischen der Methodensignatur und dem Delegattyp veranschaulicht.
' Assigning a method with a matching signature
' to a non-generic delegate. No conversion is necessary.
Dim dNonGeneric As SampleDelegate = AddressOf ASecondRFirst
' Assigning a method with a more derived return type
' and less derived argument type to a non-generic delegate.
' The implicit conversion is used.
Dim dNonGenericConversion As SampleDelegate = AddressOf AFirstRSecond
' Assigning a method with a matching signature to a generic delegate.
' No conversion is necessary.
Dim dGeneric As SampleGenericDelegate(Of Second, First) = AddressOf ASecondRFirst
' Assigning a method with a more derived return type
' and less derived argument type to a generic delegate.
' The implicit conversion is used.
Dim dGenericConversion As SampleGenericDelegate(Of Second, First) = AddressOf AFirstRSecond
Weitere Beispiele finden Sie unter Verwenden von Varianz bei Delegaten (Visual Basic) und Verwenden von Varianz für die generischen Delegaten Func und Action (Visual Basic).
Varianz in generischen Typparametern
In .NET Framework 4 oder höher können Sie implizite Konvertierung zwischen Delegaten aktivieren. Dies bedeutet, dass generische Delegaten, die über verschiedene von generischen Typparametern angegebene Typen verfügen, sich gegenseitig zugewiesen werden können, wenn die Typen voneinander geerbt werden. Dies ist für Varianz erforderlich.
Um die implizite Konvertierung zu aktivieren, müssen Sie generische Parameter in einem Delegat explizit als kovariant oder kontravariant deklarieren, indem Sie die Schlüsselwörter in oder out verwenden.
Das folgende Codebeispiel zeigt, wie Sie einen Delegaten erstellen können, der über einen kovarianten generischen Typparameter verfügt.
' Type T is declared covariant by using the out keyword.
Public Delegate Function SampleGenericDelegate(Of Out T)() As T
Sub Test()
Dim dString As SampleGenericDelegate(Of String) = Function() " "
' You can assign delegates to each other,
' because the type T is declared covariant.
Dim dObject As SampleGenericDelegate(Of Object) = dString
End Sub
Wenn Sie nur Abweichungsunterstützung verwenden, um Methodensignaturen mit Delegatentypen abzugleichen und die inout Schlüsselwörter nicht zu verwenden, stellen Sie möglicherweise fest, dass Sie manchmal Stellvertretungen mit identischen Lambda-Ausdrücken oder -Methoden instanziieren können, sie können jedoch keine Stellvertretung einem anderen zuweisen.
Im folgenden Codebeispiel SampleGenericDelegate(Of String) kann nicht explizit in SampleGenericDelegate(Of Object)konvertiert werden, obwohl String er erbt Object. Sie können dieses Problem beheben, indem Sie den generischen Parameter T mit dem out Schlüsselwort markieren.
Public Delegate Function SampleGenericDelegate(Of T)() As T
Sub Test()
Dim dString As SampleGenericDelegate(Of String) = Function() " "
' You can assign the dObject delegate
' to the same lambda expression as dString delegate
' because of the variance support for
' matching method signatures with delegate types.
Dim dObject As SampleGenericDelegate(Of Object) = Function() " "
' The following statement generates a compiler error
' because the generic type T is not marked as covariant.
' Dim dObject As SampleGenericDelegate(Of Object) = dString
End Sub
Generische Delegaten mit Variant-Typparametern im .NET Framework
.NET Framework 4 hat die Varianzunterstützung für generische Typparameter in mehreren vorhandenen generischen Delegaten eingeführt:
Action-Delegaten aus dem System-Namespace, z.B. Action<T> und Action<T1,T2>Func-Delegaten aus dem System-Namespace, z.B. Func<TResult> und Func<T,TResult>Der Predicate<T>-Delegat.
Der Comparison<T>-Delegat.
Der Converter<TInput,TOutput>-Delegat.
Weitere Informationen sowie Beispiele finden Sie unter Verwenden von Varianz für die generischen Delegaten Func und Action (Visual Basic).
Angeben varianter Typparameter in generischen Delegaten
Wenn ein generischer Delegat kovariant oder kontravariant generische Typparameter aufweist, kann er als generischer Variant-Delegat bezeichnet werden.
Sie können einen generischen Typparameter in einem generischen Delegaten mithilfe des out Schlüsselworts kovariant deklarieren. Der kovariante Typ kann nur als Methodenrückgabetyp und nicht als Typ von Methodenargumenten verwendet werden. Das folgende Codebeispiel zeigt, wie ein kovarianter generischer Delegat deklariert wird.
Public Delegate Function DCovariant(Of Out R)() As R
Sie können einen generischen Typparameter mithilfe des Schlüsselworts in in einem generischen Delegaten als kontravariant deklarieren. Der kontravariante Typ kann nur als Typ von Methodenargumenten und nicht als Methodenrückgabetyp verwendet werden. Im folgenden Codebeispiel wird veranschaulicht, wie ein kontravarianter generischer Delegat deklariert wird.
Public Delegate Sub DContravariant(Of In A)(ByVal a As A)
Von Bedeutung
ByRef Parameter in Visual Basic können nicht als Variante markiert werden.
Es ist auch möglich, Varianz und Kovarianz im gleichen Delegaten, aber für verschiedene Typparameter, zu unterstützen. Dies wird im folgenden Beispiel gezeigt.
Public Delegate Function DVariant(Of In A, Out R)(ByVal a As A) As R
Instanziieren und Aufrufen von varianten generischen Delegaten
Sie können variantente Delegaten genauso instanziieren und aufrufen, wie Sie invariante Delegaten instanziieren und aufrufen. Im folgenden Beispiel wird der Delegat durch einen Lambda-Ausdruck instanziiert.
Dim dvariant As DVariant(Of String, String) = Function(str) str + " "
dvariant("test")
Kombinieren von varianten generischen Delegaten
Sie sollten Varianten-Delegierte nicht kombinieren. Die Combine Methode unterstützt keine Variantendelegatkonvertierung und erwartet, dass Delegaten exakt denselben Typ haben. Dies kann zu einer Laufzeit Ausnahme führen, wenn Sie Delegaten entweder mithilfe der Combine Methode (in C# und Visual Basic) oder mithilfe des + Operators (in C#) kombinieren, wie im folgenden Codebeispiel gezeigt.
Dim actObj As Action(Of Object) = Sub(x) Console.WriteLine("object: {0}", x)
Dim actStr As Action(Of String) = Sub(x) Console.WriteLine("string: {0}", x)
' The following statement throws an exception at run time.
' Dim actCombine = [Delegate].Combine(actStr, actObj)
Varianz in generischen Typparametern für Wert- und Referenztypen
Die Varianz für generische Typparameter wird nur für Referenztypen unterstützt. Beispielsweise DVariant(Of Int)kann nicht implizit in DVariant(Of Object) oder DVariant(Of Long), da ganze Zahl ein Werttyp ist, konvertiert werden.
Im folgenden Beispiel wird veranschaulicht, dass die Varianz in generischen Typparametern für Werttypen nicht unterstützt wird.
' The type T is covariant.
Public Delegate Function DVariant(Of Out T)() As T
' The type T is invariant.
Public Delegate Function DInvariant(Of T)() As T
Sub Test()
Dim i As Integer = 0
Dim dInt As DInvariant(Of Integer) = Function() i
Dim dVariantInt As DVariant(Of Integer) = Function() i
' All of the following statements generate a compiler error
' because type variance in generic parameters is not supported
' for value types, even if generic type parameters are declared variant.
' Dim dObject As DInvariant(Of Object) = dInt
' Dim dLong As DInvariant(Of Long) = dInt
' Dim dVariantObject As DInvariant(Of Object) = dInt
' Dim dVariantLong As DInvariant(Of Long) = dInt
End Sub
Gelockerte Delegatenkonvertierung in Visual Basic
Gelockerte Delegatkonvertierung ermöglicht mehr Flexibilität beim Abgleichen von Methodensignaturen mit Delegattypen. So können Sie beispielsweise Parameterspezifikationen weglassen und Funktionsrückgabewerte weglassen, wenn Sie einer Stellvertretung eine Methode zuweisen. Weitere Informationen finden Sie unter Gelockerte Delegatkonvertierung.