Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier les répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer de répertoire.
.NET Framework 3.5 a introduit la prise en charge de la variance pour faire correspondre les signatures de méthode aux types délégués pour tous les délégués dans C# et Visual Basic. Cela signifie que vous pouvez affecter à des délégués non seulement des méthodes qui ont des signatures correspondantes, mais également des méthodes qui retournent des types dérivés (covariance) ou qui acceptent des paramètres qui ont moins de types dérivés (contravariance) que ceux spécifiés par le type délégué. Cela inclut les délégués génériques et non génériques.
Par exemple, considérez le code suivant, qui a deux classes et deux délégués : générique et non générique.
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
Lorsque vous créez des délégués de types SampleDelegate ou SampleDelegate(Of A, R), vous pouvez affecter l’une des méthodes suivantes à ces délégués.
' 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
L’exemple de code suivant illustre la conversion implicite entre la signature de méthode et le type délégué.
' 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
Pour plus d’exemples, consultez Utilisation de la variance dans les délégués (Visual Basic) et utilisation de variance pour les délégués génériques Func et Action (Visual Basic).
Variance dans les paramètres de type générique
Dans .NET Framework 4 et versions ultérieures, vous pouvez activer la conversion implicite entre les délégués, afin que les délégués génériques qui ont différents types spécifiés par les paramètres de type générique puissent être attribués les uns aux autres, si les types sont hérités les uns des autres, comme requis par la variance.
Pour activer la conversion implicite, vous devez déclarer explicitement des paramètres génériques dans un délégué en tant que covariant ou contravariant à l'aide du mot clé in ou out.
L’exemple de code suivant montre comment créer un délégué qui a un paramètre de type générique 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
Si vous utilisez uniquement la prise en charge de la variance pour faire correspondre les signatures de méthode avec des types délégués et que vous n'utilisez pas les mots clés in et out, vous pouvez parfois instancier des délégués avec des expressions lambda ou des méthodes identiques, mais vous ne pouvez pas affecter un délégué à un autre.
Dans l’exemple de code suivant, SampleGenericDelegate(Of String) ne peut pas être converti explicitement en SampleGenericDelegate(Of Object), bien qu’il String hérite Object. Vous pouvez résoudre ce problème en marquant le paramètre T générique avec le out mot clé.
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
Délégués génériques qui ont des paramètres de type variant dans le .NET Framework
.NET Framework 4 a introduit la prise en charge des variances pour les paramètres de type générique dans plusieurs délégués génériques existants :
Les délégués
Actionde l’espace de noms System, par exemple, Action<T> et Action<T1,T2>Les délégués
Funcde l’espace de noms System, par exemple, Func<TResult> et Func<T,TResult>Le délégué Predicate<T>
Le délégué Comparison<T>
Le délégué Converter<TInput,TOutput>
Pour plus d’informations et d’exemples, consultez Utilisation de variance pour les délégués génériques Func et Action (Visual Basic).
Déclaration de paramètres de type variant dans les délégués génériques
Si un délégué générique a des paramètres de type générique covariant ou contravariant, il peut être appelé délégué générique variant.
Vous pouvez déclarer un paramètre de type générique covariant dans un délégué générique à l’aide du out mot clé. Le type covariant ne peut être utilisé que comme type de retour de méthode et non comme type d’arguments de méthode. L’exemple de code suivant montre comment déclarer un délégué générique covariant.
Public Delegate Function DCovariant(Of Out R)() As R
Vous pouvez déclarer un paramètre de type générique contravariant dans un délégué générique à l’aide du in mot clé. Le type contravariant peut être utilisé uniquement comme type d’arguments de méthode et non comme type de retour de méthode. L’exemple de code suivant montre comment déclarer un délégué générique contravariant.
Public Delegate Sub DContravariant(Of In A)(ByVal a As A)
Importante
ByRef les paramètres de Visual Basic ne peuvent pas être marqués comme variant.
Il est également possible de prendre en charge la variance et la covariance dans le même délégué, mais pour différents paramètres de type. Ceci est illustré dans l’exemple suivant.
Public Delegate Function DVariant(Of In A, Out R)(ByVal a As A) As R
Instanciation et appel de délégués génériques variants
Vous pouvez instancier et appeler des délégués variant tout comme vous instanciez et appelez des délégués invariants. Dans l’exemple suivant, le délégué est instancié par une expression lambda.
Dim dvariant As DVariant(Of String, String) = Function(str) str + " "
dvariant("test")
Combinaison des délégués génériques variants
Vous ne devez pas combiner de délégués variants. La méthode Combine ne prend pas en charge la conversion des délégués variants et nécessite le même type pour tous les délégués. Cela peut entraîner une exception d’exécution lorsque vous combinez des délégués à l’aide de la Combine méthode (en C# et visual Basic) ou à l’aide de l’opérateur + (en C#), comme illustré dans l’exemple de code suivant.
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)
Variance dans les paramètres de type générique pour les types valeur et référence
La variance pour les paramètres de type générique est prise en charge uniquement pour les types de référence. Par exemple, DVariant(Of Int)ne peut pas être converti implicitement en DVariant(Of Object) ou DVariant(Of Long), car l’entier est un type valeur.
L’exemple suivant montre que la variance dans les paramètres de type générique n’est pas prise en charge pour les types valeur.
' 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
Conversion simplifiée des délégués dans Visual Basic
La conversion de délégué flexible permet une plus grande adaptabilité dans l'appariement des signatures de méthode avec les types de délégués. Par exemple, il vous permet d’omettre les spécifications des paramètres et des valeurs de retour de fonction lorsque vous attribuez une méthode à un délégué. Pour plus d’informations, consultez Conversion de délégué détendue.