Covariance e Contravariance (C#)

Em C#, a covariância e a contravariância permitem a conversão implícita de referência para tipos de matrizes, tipos de delegados e argumentos genéricos. A covariância preserva a compatibilidade da atribuição e a contravariância inverte-a.

O código que se segue demonstra a diferença entre compatibilidade de atribuição, covariância e contravabilidade.

// 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;  

A covariância para matrizes permite a conversão implícita de um conjunto de um tipo mais derivado para uma matriz de um tipo menos derivado. Mas esta operação não é tipo seguro, como mostra o seguinte exemplo de código.

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

O suporte à covariância e contravariância para grupos de métodos permite a correspondência de assinaturas de métodos com os tipos de delegados. Isto permite-lhe atribuir aos delegados não só métodos que tenham assinaturas correspondentes, mas também métodos que devolvem tipos mais derivados (covariância) ou que aceitam parâmetros que têm menos tipos derivados (contravariância) do que os especificados pelo tipo de delegado. Para obter mais informações, consulte Variance in Delegados (C#) e Using Variance in Delegados (C#).

O exemplo de código que se segue mostra o suporte à covariância e contravariância para 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;  
}  

Nas versões .NET Framework 4 e posteriores, C# suporta a covariância e contravariância em interfaces genéricas e delegados e permite a conversão implícita de parâmetros genéricos do tipo. Para obter mais informações, consulte Variação em Interfaces Genéricas (C#) e Variação em Delegados (C#).

O exemplo de código a seguir mostra uma conversão implícita de referência para interfaces genéricas.

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

Uma interface genérica ou delegado é chamada de variante se os seus parâmetros genéricos forem declarados covariante ou contravariante. C# permite-lhe criar as suas próprias interfaces e delegados variantes. Para obter mais informações, consulte Criar Interfaces Genéricas variantes (C#) e Variação em Delegados (C#).

Título Descrição
Variação em Interfaces Genéricas (C#) Discute a covariância e contravariância em interfaces genéricas e fornece uma lista de interfaces genéricas variantes em .NET.
Criar interfaces genéricas variantes (C#) Mostra como criar interfaces de variantes personalizadas.
Utilização de Variação em Interfaces para Coleções Genéricas (C#) Mostra como o suporte à covariância e contravariância nas IEnumerable<T> interfaces e interfaces IComparable<T> pode ajudá-lo a reutilizar o código.
Variação nos Delegados (C#) Discute a covariância e contravariância em delegados genéricos e não genéricos e fornece uma lista de delegados genéricos variantes em .NET.
Usando variação em delegados (C#) Mostra como usar o suporte de covariância e contravariância em delegados não genéricos para combinar assinaturas de métodos com tipos de delegados.
Usando variação para delegados genéricos func e de ação (C#) Mostra como o suporte à covariância e contravariância no e delegados Action pode ajudá-lo a reutilizar o Func código.