Partilhar via


Covariância e Contravariância (C#)

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

O código a seguir demonstra a diferença entre compatibilidade de atribuição, covariância e contravariância.

// 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 uma matriz de um tipo mais derivado para uma matriz de um tipo menos derivado. Mas essa operação não é segura de tipo, como mostrado no exemplo de código a seguir.

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

O suporte a covariância e contravariância para grupos de métodos permite a correspondência de assinaturas de método com tipos delegados. Isso permite que você atribua aos delegados não apenas métodos que tenham assinaturas correspondentes, mas também métodos que retornem mais tipos derivados (covariância) ou que aceitem parâmetros que tenham menos tipos derivados (contravariância) do que os especificados pelo tipo delegado. Para obter mais informações, consulte Variância em Delegados (C#) e Usando Variância em Delegados (C#).

O exemplo de código a seguir mostra suporte a covariância e contravariância para grupos de método.

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

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

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

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

Uma interface genérica ou delegado é chamada(o) de variante se os seus parâmetros genéricos forem declarados covariante ou contravariante. C# permite-lhe criar interfaces e delegações personalizáveis. Para obter mais informações, consulte Criação de Interfaces Genéricas Variantes (C#) e Variância em Delegados (C#).

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