Covarianza y contravarianza (C#)
En C#, la covarianza y la contravarianza habilitan la conversión de referencias implícita de tipos de matriz, tipos de delegado y argumentos de tipo genérico. La covarianza conserva la compatibilidad de asignaciones y la contravarianza la invierte.
El siguiente código 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 de 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, tal 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 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. Para obtener más información, vea Varianza en delegados (C#) y Usar varianza en delegados (C#).
En el ejemplo de código siguiente, se muestra la compatibilidad de covarianza y contravarianza con 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 o versiones posteriores, C# admite la covarianza y contravarianza en las interfaces genéricas y los delegados, y permite 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 Varianza en delegados (C#).
En el ejemplo de código siguiente, se muestra la conversión implícita de referencias para interfaces genéricas.
IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;
Un delegado o interfaz genéricos se denominan variante si sus parámetros genéricos se declaran como covariantes o contravariantes. 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#).
Temas relacionados
Title | Descripción |
---|---|
Varianza en interfaces genéricas (C#) | Describe la covarianza y contravarianza en las interfaces genéricas y proporciona una lista de interfaces genéricas variantes en .NET. |
Crear interfaces genéricas variantes (C#) | Se muestra cómo crear interfaces variantes personalizadas. |
Usar la varianza en interfaces para las colecciones genéricas (C#) | Se muestra cómo la compatibilidad de covarianza y contravarianza en las interfaces IEnumerable<T> y IComparable<T> puede ayudarle a volver a usar 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. |
Usar varianza 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. |