Covarianza y contravarianza (C# y Visual Basic)

En C# y Visual Basic, la covarianza y la contravarianza permiten la conversión implícita de referencias para los tipos de matriz, los tipos de delegado y los argumentos de tipo genérico. La covarianza mantiene la compatibilidad con la asignación y la contravarianza la invierte.

El código siguiente muestra la diferencia entre la compatibilidad de la asignación, la covarianza y la contravarianza.

' Assignment compatibility. 
Dim str As String = "test"
' An object of a more derived type is assigned to an object of a less derived type. 
Dim obj As Object = str

' Covariance. 
Dim strings As IEnumerable(Of String) = New List(Of String)()
' An object that is instantiated with a more derived type argument 
' is assigned to an object instantiated with a less derived type argument. 
' Assignment compatibility is preserved. 
Dim objects As IEnumerable(Of Object) = strings

' Contravariance.           
' Assume that there is the following method in the class: 
' Shared Sub SetObject(ByVal o As Object)
' End Sub
Dim actObject As Action(Of Object) = AddressOf SetObject

' An object that is instantiated with a less derived type argument 
' is assigned to an object instantiated with a more derived type argument. 
' Assignment compatibility is reversed. 
Dim actString As Action(Of String) = actObject
// Assignment compatibility. 
string str = "test";
// An object of a more derived type is assigned to an object of a less derived type. 
object obj = str;

// Covariance. 
IEnumerable<string> strings = new List<string>();
// An object that is instantiated with a more derived type argument 
// is assigned to an object instantiated with a less derived type argument. 
// Assignment compatibility is preserved. 
IEnumerable<object> objects = strings;

// Contravariance.           
// Assume that the following method is in the class: 
// static void SetObject(object o) { } 
Action<object> actObject = SetObject;
// An object that is instantiated with a less derived type argument 
// is assigned to an object instantiated with a more derived type argument. 
// Assignment compatibility is reversed. 
Action<string> actString = actObject;

La covarianza para matrices habilita la conversión implícita de una matriz de un tipo más derivado en una matriz de un tipo menos derivado. Pero estas operaciones no cuentan con seguridad de tipos, tal y como se muestra en el ejemplo de código siguiente.

Dim array() As Object = New String(10) {}
' The following statement produces a run-time exception.
' array(0) = 10
object[] array = new String[10];
// The following statement produces a run-time exception.
// array[0] = 10;

La compatibilidad con la covarianza y contravarianza en los grupos de métodos permite las firmas de método que coinciden con los tipos de delegado. Esto permite asignar a los delegados no solo los métodos con firmas coincidentes, sino también los métodos que devuelven tipos más derivados (covarianza) o que aceptan parámetros que tienen tipos menos derivados (contravarianza) de los especificados por el tipo de delegado. Para obtener más información, vea Varianza en delegados (C# y Visual Basic) y Utilizar varianza en delegados (C# y Visual Basic).

En el ejemplo de código siguiente se muestra la compatibilidad con la covarianza y contravarianza en los grupos de métodos.

Shared Function GetObject() As Object
    Return Nothing
End Function

Shared Sub SetObject(ByVal obj As Object)
End Sub

Shared Function GetString() As String
    Return ""
End Function

Shared Sub SetString(ByVal str As String)

End Sub

Shared Sub Test()
    ' Covariance. A delegate specifies a return type as object,
    ' but you can assign a method that returns a string.
    Dim del As Func(Of Object) = AddressOf GetString

    ' Contravariance. A delegate specifies a parameter type as string,
    ' but you can assign a method that takes an object.
    Dim del2 As Action(Of String) = AddressOf SetObject
End Sub
static object GetObject() { return null; }
static void SetObject(object obj) { }

static string GetString() { return ""; }
static void SetString(string str) { }

static void Test()
{
    // Covariance. A delegate specifies a return type as object,
    // but you can assign a method that returns a string.
    Func<object> del = GetString;

    // Contravariance. A delegate specifies a parameter type as string,
    // but you can assign a method that takes an object.
    Action<string> del2 = SetObject;
}

En .NET Framework 4 y Visual Studio 2010, tanto C# como Visual Basic admiten la covarianza y la contravarianza en las interfaces y los delegados genéricos y permiten la conversión implícita de los parámetros de tipo genérico. Para obtener más información, vea Varianza en interfaces genéricas (C# y Visual Basic) y Varianza en delegados (C# y Visual Basic).

En el ejemplo de código siguiente se muestra la conversión de referencias implícita para las interfaces genéricas.

Dim strings As IEnumerable(Of String) = New List(Of String)
Dim objects As IEnumerable(Of Object) = strings
IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;

Una interfaz o un delegado de tipo genérico se denomina variante si sus parámetros genéricos se declaran como covariantes o contravariantes. Tanto C# como Visual Basic le permiten crear sus propios delegados e interfaces variantes. Para obtener más información, vea Crear interfaces genéricas variantes (C# y Visual Basic) y Varianza en delegados (C# y Visual Basic).

Temas relacionados

Título

Descripción

Varianza en interfaces genéricas (C# y Visual Basic)

Se describe la covarianza y la contravarianza en las interfaces genéricas y se proporciona una lista de interfaces genéricas variantes en .NET Framework.

Crear interfaces genéricas variantes (C# y Visual Basic)

Se muestra cómo crear interfaces variantes personalizadas.

Usar la varianza en interfaces para las colecciones genéricas (C# y Visual Basic)

Se muestra cómo puede ayudarle a reutilizar el código la compatibilidad con la covarianza y contravarianza en las interfaces IEnumerable<T> y IComparable<T>.

Varianza en delegados (C# y Visual Basic)

Se describen la covarianza y contravarianza en los delegados genéricos y no genéricos y se proporciona una lista de los delegados genéricos variantes en .NET Framework.

Utilizar varianza en delegados (C# y Visual Basic)

Se muestra cómo usar la compatibilidad con la covarianza y contravarianza en los delegados no genéricos para hacer coincidir las firmas de método con los tipos de delegado.

Usar la varianza para los delegados genéricos Func y Action (C# y Visual Basic)

Se muestra cómo puede ayudarle a reutilizar el código la compatibilidad con la covarianza y contravarianza en los delegados Func y Action.