Varianza en delegados (Visual Basic)Variance in Delegates (Visual Basic)

.NET framework 3.5 introdujo la compatibilidad con la varianza para hacer coincidir firmas de método con tipos de delegado en todos los delegados en C# y Visual Basic..NET Framework 3.5 introduced variance support for matching method signatures with delegate types in all delegates in C# and Visual Basic. Esto significa que puede asignar a los delegados no solo métodos con firmas coincidentes, sino métodos que devuelven tipos más derivados (covarianza) o que aceptan parámetros con tipos menos derivados (contravarianza) que el especificado por el tipo de delegado.This means that you can assign to delegates not only methods that have matching signatures, but also methods that return more derived types (covariance) or that accept parameters that have less derived types (contravariance) than that specified by the delegate type. Esto incluye delegados genéricos y no genéricos.This includes both generic and non-generic delegates.

Por ejemplo, consideremos el siguiente código, que tiene dos clases y dos delegados: genéricos y no genéricos.For example, consider the following code, which has two classes and two delegates: generic and non-generic.

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

Al crear delegados de los tipos SampleDelegate o SampleDelegate(Of A, R), puede asignar uno de los métodos siguientes a dichos delegados.When you create delegates of the SampleDelegate or SampleDelegate(Of A, R) types, you can assign any one of the following methods to those delegates.

' 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

En el ejemplo de código siguiente se ilustra la conversión implícita entre la firma del método y el tipo de delegado.The following code example illustrates the implicit conversion between the method signature and the delegate type.

' 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

Para obtener más ejemplos, vea usar varianza en delegados (Visual Basic) y Using Variance for Func and Action Generic Delegates (Visual Basic).For more examples, see Using Variance in Delegates (Visual Basic) and Using Variance for Func and Action Generic Delegates (Visual Basic).

Varianza en parámetros de tipo genéricoVariance in Generic Type Parameters

En .NET Framework 4 y versiones posteriores puede habilitar la conversión implícita entre los delegados, para que los delegados genéricos con tipos diferentes especificados por los parámetros de tipo genérico pueden asignarse entre sí, si los tipos se hereden entre sí según sea necesario por varianza.In .NET Framework 4 and later you can enable implicit conversion between delegates, so that generic delegates that have different types specified by generic type parameters can be assigned to each other, if the types are inherited from each other as required by variance.

Para habilitar la conversión implícita, debe declarar explícitamente parámetros genéricos en un delegado como covariante o contravariante mediante la palabra clave in o out.To enable implicit conversion, you must explicitly declare generic parameters in a delegate as covariant or contravariant by using the in or out keyword.

En el ejemplo de código siguiente se muestra cómo se crea un delegado que tiene un parámetro de tipo genérico covariante.The following code example shows how you can create a delegate that has a covariant generic type parameter.

' 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 usa solo la compatibilidad con la varianza para hacer coincidir firmas de método con tipos de delegados y no usa las palabras clave in y out, es posible que en algunas ocasiones pueda crear instancias de delegados con métodos o expresiones lambda idénticos, pero no pueda asignar un delegado a otro.If you use only variance support to match method signatures with delegate types and do not use the in and out keywords, you may find that sometimes you can instantiate delegates with identical lambda expressions or methods, but you cannot assign one delegate to another.

En el ejemplo de código siguiente, SampleGenericDelegate(Of String) no se puede convertir explícitamente a SampleGenericDelegate(Of Object), aunque String hereda Object.In the following code example, SampleGenericDelegate(Of String) can't be explicitly converted to SampleGenericDelegate(Of Object), although String inherits Object. Para solucionar este problema, marque el parámetro genérico T con la palabra clave out.You can fix this problem by marking the generic parameter T with the out keyword.

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

Delegados genéricos con parámetros de tipo variante en .NET FrameworkGeneric Delegates That Have Variant Type Parameters in the .NET Framework

En .NET Framework 4 se presentó por primera vez la compatibilidad con la varianza para los parámetros de tipo genérico en varios delegados genéricos existentes:.NET Framework 4 introduced variance support for generic type parameters in several existing generic delegates:

Para obtener más información y ejemplos, vea Using Variance for Func and Action Generic Delegates (Visual Basic).For more information and examples, see Using Variance for Func and Action Generic Delegates (Visual Basic).

Declarar parámetros de tipo variante en delegados genéricosDeclaring Variant Type Parameters in Generic Delegates

Si un delegado genérico tiene parámetros de tipo genérico covariante o contravariante, se puede hacer referencia a él como un delegado genérico variante.If a generic delegate has covariant or contravariant generic type parameters, it can be referred to as a variant generic delegate.

Puede declarar un parámetro de tipo genérico covariante en un delegado genérico mediante la palabra clave out.You can declare a generic type parameter covariant in a generic delegate by using the out keyword. El tipo covariante puede usarse solo como un tipo de valor devuelto de método, y no como un tipo de argumentos de método.The covariant type can be used only as a method return type and not as a type of method arguments. En el siguiente ejemplo de código se muestra cómo declarar un delegado genérico covariante.The following code example shows how to declare a covariant generic delegate.

Public Delegate Function DCovariant(Of Out R)() As R

Puede declarar un parámetro de tipo genérico contravariante en un delegado genérico mediante la palabra clave in.You can declare a generic type parameter contravariant in a generic delegate by using the in keyword. El tipo contravariante puede usarse solo como un tipo de argumentos de método, y no como un tipo de valor devuelto de método.The contravariant type can be used only as a type of method arguments and not as a method return type. En el siguiente ejemplo de código se muestra cómo declarar un delegado genérico contravariante.The following code example shows how to declare a contravariant generic delegate.

Public Delegate Sub DContravariant(Of In A)(ByVal a As A)

Importante

ByRef los parámetros en Visual Basic no se pueden marcar como variantes.ByRef parameters in Visual Basic can't be marked as variant.

También es posible admitir la varianza y la covarianza en el mismo delegado, pero para parámetros de tipo diferentes.It is also possible to support both variance and covariance in the same delegate, but for different type parameters. Esta implementación se muestra en el ejemplo siguiente.This is shown in the following example.

Public Delegate Function DVariant(Of In A, Out R)(ByVal a As A) As R

Crear instancias de delegados genéricos variantes e invocarlosInstantiating and Invoking Variant Generic Delegates

Puede crear instancias de delegados variantes e invocarlos del mismo modo que crea instancias de delegados invariables y los invoca.You can instantiate and invoke variant delegates just as you instantiate and invoke invariant delegates. En el ejemplo siguiente, se crea una instancia del delegado mediante una expresión lambda.In the following example, the delegate is instantiated by a lambda expression.

Dim dvariant As DVariant(Of String, String) = Function(str) str + " "
dvariant("test")

Combinar delegados genéricos variantesCombining Variant Generic Delegates

No debe combinar delegados variantes.You should not combine variant delegates. El método Combine no admite la conversión de delegados variantes y espera que los delegados sean exactamente del mismo tipo.The Combine method does not support variant delegate conversion and expects delegates to be of exactly the same type. Esto puede provocar una excepción de tiempo de ejecución cuando se combinan delegados mediante la Combine (método) (en C# y Visual Basic) o mediante el + operador (en C#), tal y como se muestra en el siguiente ejemplo de código.This can lead to a run-time exception when you combine delegates either by using the Combine method (in C# and Visual Basic) or by using the + operator (in C#), as shown in the following code example.

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)

Varianza en parámetros de tipo genérico para los tipos de referencia y valorVariance in Generic Type Parameters for Value and Reference Types

La varianza para parámetros de tipo genérico solo es compatible con tipos de referencia.Variance for generic type parameters is supported for reference types only. Por ejemplo, DVariant(Of Int)no se puede convertir implícitamente a DVariant(Of Object) o DVariant(Of Long), dado que entero es un tipo de valor.For example, DVariant(Of Int)can't be implicitly converted to DVariant(Of Object) or DVariant(Of Long), because integer is a value type.

En el ejemplo siguiente se muestra que la varianza en parámetros de tipo genérico no se admite para tipos de valor.The following example demonstrates that variance in generic type parameters is not supported for value types.

' 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

Conversión de delegado flexible en Visual BasicRelaxed Delegate Conversion in Visual Basic

Conversión de delegado flexible permite más flexibilidad para hacer coincidir firmas de método con tipos de delegado.Relaxed delegate conversion enables more flexibility in matching method signatures with delegate types. Por ejemplo, permite omitir las especificaciones de parámetro y omite los valores devueltos de función al asignar un método a un delegado.For example, it lets you omit parameter specifications and omit function return values when you assign a method to a delegate. Para obtener más información, consulte conversión de delegado flexible.For more information, see Relaxed Delegate Conversion.

Vea tambiénSee also