Compartir a través de


Covarianza y contravarianza (C#)

En C#, la covarianza y la contravarianza permiten la conversión de referencia implícita para los tipos de matriz, los tipos delegados y los argumentos de tipo genérico. La covarianza conserva la compatibilidad de asignaciones y la contravarianza la invierte.

En el código siguiente se muestra la diferencia entre la compatibilidad de asignaciones, la covarianza y la contravarianza.

// 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 permite la conversión implícita de una matriz de un tipo más derivado a una matriz de un tipo menos derivado. Pero esta operación no es segura para tipos, como se muestra en el ejemplo de código siguiente.

object[] array = new String[10];  
// The following statement produces a run-time exception.  
// array[0] = 10;  

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

En el siguiente ejemplo de código se muestra el soporte de covarianza y contravarianza para los grupos de métodos.

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 versiones posteriores, C# admite covarianza y contravarianza en interfaces y delegados genéricos y permite la conversión implícita de parámetros de tipo genérico. Para obtener más información, vea Varianza en interfaces genéricas (C#) y Varianza en delegados (C#).

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

IEnumerable<String> strings = new List<String>();  
IEnumerable<Object> objects = strings;  

Una interfaz genérica o delegado se denomina variant si sus parámetros genéricos se declaran covariante o contravariante. C# le permite crear sus propias interfaces y delegados variantes. Para obtener más información, consulte Crear interfaces genéricas variantes (C#) y Varianza en delegados (C#).

Título Descripción
Varianza en interfaces genéricas (C#) Describe la covarianza y la contravarianza en interfaces genéricas y proporciona una lista de interfaces genéricas variantes en .NET.
Creando interfaces genéricas variantes (C#) Muestra cómo crear interfaces variantes personalizadas.
Usar varianza en interfaces para colecciones genéricas (C#) Muestra cómo la compatibilidad con covarianza y contravarianza en las interfaces IEnumerable<T> y IComparable<T> puede ayudarle a reutilizar el código.
Varianza en delegados (C#) Se describe la covarianza y contravarianza en delegados genéricos y no genéricos y se proporciona una lista de delegados genéricos variantes en .NET.
Usar varianza en delegados (C#) Se muestra cómo usar la compatibilidad de covarianza y contravarianza en los delegados no genéricos para que coincidan las firmas de método con los tipos de delegado.
Uso de la variación para los delegados genéricos Func y Action (C#) Se muestra cómo la compatibilidad de covarianza y contravarianza en los delegados Func y Action puede ayudarle a volver a usar el código.