Condividi tramite


Covarianza e controvarianza (C#)

In C#, covarianza e controvarianza consentono la conversione implicita dei riferimenti per tipi di matrice, tipi delegati e argomenti di tipo generico. La Covarianza mantiene la compatibilità delle assegnazioni e la controvarianza la inverte.

Il codice seguente illustra la differenza tra compatibilità delle assegnazioni, 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. Questa operazione non è sicura per i 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 permette di abbinare le signature dei metodi con i tipi delegati. In questo modo è possibile assegnare ai delegati non solo i metodi con firme corrispondenti, ma anche i metodi che restituiscono tipi più derivati (covarianza) o che accettano parametri con tipi meno 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 della covarianza e della 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 generico. Per altre informazioni, vedere Varianza nelle interfacce generiche (C#) e varianza nei delegati (C#).

Nell'esempio di codice seguente viene illustrata la conversione implicita dei riferimenti per le interfacce generiche.

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

Un'interfaccia o un delegato generico viene chiamato variant se i relativi parametri generici sono dichiarati covarianti o controvarianti. C# consente di creare interfacce e delegati varianti personalizzati. Per altre informazioni, vedere Creazione di Interfacce Generiche Varianti (C#) e Varianza nei Delegati (C#).

Titolo Descrizione
Varianza nelle interfacce generiche (C#) Viene descritta la covarianza e la controvarianza nelle interfacce generiche e viene fornito un elenco di interfacce generiche varianti in .NET.
Creazione di interfacce generiche varianti (C#) Illustra come creare interfacce varianti personalizzate.
Uso della varianza nelle interfacce per le raccolte generiche (C#) Illustra in che modo il supporto della covarianza e della controvarianza nelle interfacce IEnumerable<T> e IComparable<T> consente di riutilizzare il codice.
Varianza dei Delegati (C#) Descrive la covarianza e la controvarianza nei delegati generici e non generici e fornisce un elenco di delegati generici varianti in .NET.
Uso della varianza nei delegati (C#) Illustra come usare il sostegno della covarianza e della controvarianza nei delegati non generici per far combaciare le firme dei metodi con i tipi di delegato.
Uso della varianza per i delegati generici func e action (C#) Illustra in che modo il supporto della covarianza e della controvarianza nei Func e Action delegati può aiutarti a riutilizzare il codice.