Afwijking in gemachtigden (Visual Basic)
.NET Framework 3.5 heeft variantieondersteuning geïntroduceerd voor overeenkomende methodehandtekeningen met gedelegeerdentypen in alle gemachtigden in C# en Visual Basic. Dit betekent dat u niet alleen methoden kunt toewijzen aan gedelegeerden die overeenkomende handtekeningen hebben, maar ook methoden die meer afgeleide typen (covariantie) retourneren of parameters accepteren die minder afgeleide typen (contravariantie) hebben dan die zijn opgegeven door het gemachtigdetype. Dit omvat zowel algemene als niet-algemene gemachtigden.
Denk bijvoorbeeld aan de volgende code, die twee klassen en twee gemachtigden heeft: algemeen en niet-algemeen.
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
Wanneer u gemachtigden van de SampleDelegate
of SampleDelegate(Of A, R)
typen maakt, kunt u een van de volgende methoden toewijzen aan deze gemachtigden.
' 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
In het volgende codevoorbeeld ziet u de impliciete conversie tussen de methodehandtekening en het type gemachtigde.
' 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
Zie Afwijking gebruiken in Gedelegeerden (Visual Basic) en Variantie gebruiken voor Func en Action Generic Delegates (Visual Basic) voor meer voorbeelden.
Afwijking in algemene typeparameters
In .NET Framework 4 en hoger kunt u impliciete conversie tussen gemachtigden inschakelen, zodat algemene gemachtigden met verschillende typen die door algemene typeparameters zijn opgegeven, aan elkaar kunnen worden toegewezen als de typen worden overgenomen van elkaar, afhankelijk van variantie.
Als u impliciete conversie wilt inschakelen, moet u expliciet algemene parameters in een gemachtigde declareren als covariant of contravariant met behulp van het in
of out
trefwoord.
In het volgende codevoorbeeld ziet u hoe u een gemachtigde kunt maken met een parameter voor het algemene type covariant.
' 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
Als u alleen variantieondersteuning gebruikt om methodehandtekeningen te vergelijken met gedelegeerdentypen en de in
trefwoorden out
niet gebruikt, kunt u soms gedelegeerden instantiëren met identieke lambda-expressies of -methoden, maar u kunt geen gedelegeerde aan een andere gemachtigde toewijzen.
In het volgende codevoorbeeld SampleGenericDelegate(Of String)
kan niet expliciet worden geconverteerd naar SampleGenericDelegate(Of Object)
, hoewel String
overgenomen Object
. U kunt dit probleem oplossen door de algemene parameter T
te markeren met het out
trefwoord.
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
Algemene gemachtigden met varianttypeparameters in .NET Framework
.NET Framework 4 heeft variantieondersteuning geïntroduceerd voor algemene typeparameters in verschillende bestaande algemene gemachtigden:
Action
gemachtigden uit de System naamruimte, bijvoorbeeld Action<T> en Action<T1,T2>Func
gemachtigden uit de System naamruimte, bijvoorbeeld Func<TResult> en Func<T,TResult>De Predicate<T> gedelegeerde
De Comparison<T> gedelegeerde
De Converter<TInput,TOutput> gedelegeerde
Zie Variantie gebruiken voor Func en Action Generic Delegates (Visual Basic) voor meer informatie en voorbeelden.
Parameters voor varianttype declareren in algemene gemachtigden
Als een algemene gemachtigde covariant of contravariant algemene typeparameters heeft, kan deze worden aangeduid als een variant algemene gemachtigde.
U kunt een algemene parametercovariant in een algemene gemachtigde declareren met behulp van het out
trefwoord. Het covarianttype kan alleen worden gebruikt als retourtype voor een methode en niet als een type methodeargumenten. In het volgende codevoorbeeld ziet u hoe u een covariant algemene gemachtigde declareert.
Public Delegate Function DCovariant(Of Out R)() As R
U kunt een algemene parameterparameter contravariant in een algemene gemachtigde declareren met behulp van het in
trefwoord. Het contravarianttype kan alleen worden gebruikt als een type methodeargumenten en niet als retourtype methode. In het volgende codevoorbeeld ziet u hoe u een algemene gemachtigde voor contravariant declareert.
Public Delegate Sub DContravariant(Of In A)(ByVal a As A)
Belangrijk
ByRef
parameters in Visual Basic kunnen niet worden gemarkeerd als variant.
Het is ook mogelijk om zowel variantie als covariantie in dezelfde gemachtigde te ondersteunen, maar voor verschillende typeparameters. Dit wordt weergegeven in het volgende voorbeeld.
Public Delegate Function DVariant(Of In A, Out R)(ByVal a As A) As R
Algemene gedelegeerden instantiëren en aanroepen van varianten
U kunt variantendelegeringen instantiëren en aanroepen, net zoals u invariante gedelegeerden instantieert en aanroept. In het volgende voorbeeld wordt de gemachtigde geïnstantieerd door een lambda-expressie.
Dim dvariant As DVariant(Of String, String) = Function(str) str + " "
dvariant("test")
Variant algemene gemachtigden combineren
U moet variantendelegen niet combineren. De Combine methode biedt geen ondersteuning voor conversie van variantdelegen en verwacht dat gemachtigden precies hetzelfde type hebben. Dit kan leiden tot een runtime-uitzondering wanneer u gemachtigden combineert met behulp van de Combine methode (in C# en Visual Basic) of met behulp van de +
operator (in C#), zoals wordt weergegeven in het volgende codevoorbeeld.
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)
Variantie in algemene typeparameters voor waarde- en verwijzingstypen
Variantie voor algemene typeparameters wordt alleen ondersteund voor referentietypen. Kan bijvoorbeeld DVariant(Of Int)
niet impliciet worden geconverteerd naar DVariant(Of Object)
of DVariant(Of Long)
, omdat een geheel getal een waardetype is.
In het volgende voorbeeld ziet u dat variantie in algemene typeparameters niet wordt ondersteund voor waardetypen.
' 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
Ontspannen conversie van gemachtigden in Visual Basic
Ontspannen conversie van gemachtigden maakt meer flexibiliteit mogelijk bij het vergelijken van methodehandtekeningen met gedelegeerdentypen. U kunt bijvoorbeeld parameterspecificaties weglaten en functiewaarden weglaten wanneer u een methode aan een gemachtigde toewijst. Zie Ontspannen conversie van gedelegeerden voor meer informatie.