Condividi tramite


Covarianza e controvarianza (C#)

In C#, covarianza e controvarianza abilitano la conversione implicita del riferimento per i tipi di matrice, i tipi delegati e gli argomenti di tipo generico. La covarianza mantiene la compatibilità dell'assegnazione e la controvarianza la inverte.

Il codice seguente illustra la differenza tra la compatibilità dell'assegnazione, covarianza e controvarianza.

// 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 per le matrici consente la conversione implicita di una matrice di un tipo più derivato in una matrice di un tipo meno derivato. Ma questa operazione non è indipendente dai tipi, come illustrato nell'esempio di codice seguente.

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

Il supporto di covarianza e controvarianza per i gruppi di metodi consente la corrispondenza delle firme del metodo con i tipi delegati. Ciò consente di assegnare ai delegati non solo i metodi con firme corrispondenti, ma anche i metodi che restituiscono più tipi derivati (covarianza) o accettano parametri con meno tipi derivati (controvarianza) rispetto a quelli specificati dal tipo delegato. Per altre informazioni, vedere Varianza nei delegati (C#) e Uso della varianza nei delegati (C#).

L'esempio di codice seguente illustra il supporto di covarianza e controvarianza per i gruppi di metodi.

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

In .NET Framework 4 e versioni successive, C# supporta covarianza e controvarianza in interfacce e delegati generici e consente la conversione implicita di parametri di tipo generici. Per altre informazioni, vedere Varianza nelle interfacce generiche (C#) e Varianza nei delegati (C#).

L'esempio di codice seguente illustra la conversione implicita del riferimento per le interfacce generiche.

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

Le interfacce o i delegati generici sono detti varianti se i relativi parametri generici vengono dichiarati come covarianti o controvarianti. C# consente di creare i propri delegati e interfacce varianti. Per altre informazioni, vedere Creazione di interfacce generiche varianti (C#) e Varianza nei delegati (C#).

Titolo Descrizione
Varianza nelle interfacce generiche (C#) Illustra covarianza e controvarianza nelle interfacce generiche e fornisce un elenco di interfacce generiche varianti in .NET.
Creazione di interfacce generiche varianti (C#) Spiega come creare interfacce varianti personalizzate.
Uso della varianza nelle interfacce per le raccolte generiche (C#) Spiega come il supporto di covarianza e controvarianza nelle interfacce IEnumerable<T> e IComparable<T> consente di riutilizzare il codice.
Varianza nei delegati (C#) Illustra la covarianza e la controvarianza in delegati generici e non generici e fornisce un elenco di delegati generici varianti in .NET.
Uso della varianza nei delegati (C#) Spiega come usare il supporto di covarianza e controvarianza nei delegati non generici per la corrispondenza delle firme del metodo con i tipi delegati.
Uso della varianza per i delegati generici Func e Action (C#) Spiega come il supporto di covarianza e controvarianza nei delegati Func e Action consente di riutilizzare il codice.