Per visualizzare l'articolo in inglese, selezionare la casella di controllo Inglese. È possibile anche visualizzare il testo inglese in una finestra popup posizionando il puntatore del mouse sopra il testo.
Traduzione
Inglese

Generics in .NET Framework

 

Data di pubblicazione: ottobre 2016

I generics consentono di personalizzare un metodo, una classe o una struttura in base ai dati precisi su cui interviene. Ad esempio, invece di usare la classe Hashtable, che consente di avere chiavi e valori di ogni tipo, è possibile usare la classe generica Dictionary<TKey, TValue> e specificare il tipo concesso per la chiave e quello concesso per il valore. Tra i vantaggi dei generics ci sono una maggiore riutilizzabilità del codice e l'indipendenza dai tipi.

In questo argomento vengono forniti una panoramica dei generics nel.NET Framework e un riepilogo dei tipi o metodi generici. Include le sezioni seguenti:

I generics sono classi, strutture, interfacce e metodi dotati di segnaposto (parametri di tipo) per uno o più dei tipi archiviati o usati. Una classe di raccolte generiche può usare un parametro di tipo come segnaposto per il tipo di oggetti in essa contenuti. I parametri di tipo vengono visualizzati come i tipi dei relativi campi e i tipi di parametri dei relativi metodi. Un metodo generico potrebbe usare il parametro di tipo come il tipo di valore restituito o come il tipo di uno dei parametri formali. Nel codice seguente viene illustrata una definizione di classe generica semplice.

public class Generic<T>
{
    public T Field;
}

Quando si crea un'istanza di una classe generica, è possibile specificare i tipi effettivi da sostituire per i parametri di tipo. Ciò consente di stabilire una nuova classe generica, definita come una classe generica costruita, con tipi prescelti sostituiti a ogni occorrenza dei parametri di tipo. Il risultato è una classe indipendente dai tipi personalizzata in base alla scelta di tipi, come illustrato nel codice seguente.

public static void Main()
{
    Generic<string> g = new Generic<string>();
    g.Field = "A string";
    //...
    Console.WriteLine("Generic.Field           = \"{0}\"", g.Field);
    Console.WriteLine("Generic.Field.GetType() = {0}", g.Field.GetType().FullName);
}

I termini seguenti vengono usati per discutere dei generics in .NET Framework:

  • Una definizione di tipo generico è una classe, una struttura o una dichiarazione di interfaccia che funge da modello, con segnaposto per i tipi che può contenere o usare. Ad esempio, la classe System.Collections.Generic.Dictionary<TKey, TValue> può contenere due tipi: chiavi e valori. Poiché una definizione di tipo generico è solo un modello, non è possibile creare istanze di una classe, una struttura o un'interfaccia che sia una definizione di tipo generico.

  • I parametri di tipo generico, o parametri di tipo, sono i segnaposto in una definizione di tipo o metodo generico. Il tipo generico System.Collections.Generic.Dictionary<TKey, TValue> ha due parametri di tipo, TKey e TValue, che rappresentano i tipi delle chiavi e dei valori relativi.

  • Un tipo generico costruito, o tipo costruito, è il risultato della specifica di tipi per i parametri di tipo generico di una definizione di tipo generico.

  • Un argomento di tipo generico è qualsiasi tipo che verrà sostituito con un parametro di tipo generico.

  • Il termine generale tipo generico include sia tipi costruiti sia definizioni di tipo generico.

  • La covarianza e la controvarianza dei parametri di tipo generico consentono di usare tipi generici costruiti i cui argomenti di tipo sono più derivati (covarianza) o meno derivati (controvarianza) rispetto a quelle di tipo costruito. La covarianza e la controvarianza sono definite collettivamente varianza. Per altre informazioni, vedere Covarianza e controvarianza nei generics.

  • I vincoli sono limiti imposti su parametri di tipo generico. Ad esempio, è possibile limitare un parametro di tipo a tipi che implementano l'interfaccia generica System.Collections.Generic.IComparer<T>, per garantire la possibilità di ordinare le istanze del tipo. È anche possibile vincolare i parametri di tipo a tipi che dispongono di una determinata classe di base, con un costruttore predefinito, o che siano tipi riferimento o tipi di valore. Gli utenti di tipo generico non possono sostituire gli argomenti di tipo che non soddisfano i vincoli.

  • Una definizione di metodo generico è un metodo con due elenchi di parametri: un elenco di parametri di tipo generico e un elenco di parametri formali. I parametri di tipo possono apparire come tipo restituito o come tipi dei parametri formali, come illustrato nel codice seguente.

T Generic<T>(T arg)
{
    T temp = arg;
    //...
    return temp;
}

I metodi generici possono apparire su tipi generici o non generici. È importante tenere presente che un metodo si definisce non generico solo perché appartiene a un tipo generico o perché ha parametri formali i cui tipi sono i parametri generici del tipo contenitore. Un metodo è generico solo se ha un proprio elenco di parametri di tipo. Nel codice seguente, solo il metodo G è generico.

class A
{
    T G<T>(T arg)
    {
        T temp = arg;
        //...
        return temp;
    }
}
class Generic<T>
{
    T M(T arg)
    {
        T temp = arg;
        //...
        return temp;
    }
}

Torna all'inizio

Esistono numerosi vantaggi nell'utilizzo di delegati e raccolte di tipi generici:

  • Indipendenza dai tipi. I generics spostano il carico dell'indipendenza dai tipi al compilatore. Non è necessario scrivere codice per verificare il tipo di dati corretto perché viene applicato in fase di compilazione. La necessità del cast di tipo e la possibilità di errori di run-time sono ridotte.

  • Meno codice e il codice è più facilmente riutilizzato. Non è necessario ereditare da un tipo di base ed eseguire l'override di membri. Ad esempio, LinkedList<T> è pronto per l'uso immediato. Ad esempio, è possibile creare un elenco collegato di stringhe con la seguente dichiarazione di variabile:

    LinkedList<string> llist = new LinkedList<string>();
    
  • Prestazioni migliori. I tipi di raccolte generiche offrono in genere prestazioni migliori per l'archiviazione e la modifica dei tipi di valore, perché non è necessario eseguirne il boxing.

  • I delegati generici consentono di eseguire il callback indipendente dai tipi senza la necessità di creare più classi delegate. Ad esempio, il delegato generico Predicate<T> consente di creare un metodo per implementare i propri criteri di ricerca di un tipo particolare e di usare il proprio metodo con metodi di tipo Array, ad esempio Find<T>, FindLast<T> e FindAll<T>.

  • I generics ottimizzano il codice generato dinamicamente. Quando si usano i generics con il codice generato in modo dinamico non è necessario generare il tipo. In questo modo aumenta il numero di scenari in cui è possibile usare i metodi dinamici leggeri invece di generare interi assembly. Per altre informazioni, vedere Procedura: definire ed eseguire metodi dinamici e DynamicMethod.

Di seguito sono elencate alcune limitazioni di generics:

  • I tipi generici possono derivare dalla maggior parte delle classi base, ad esempio MarshalByRefObject (e i vincoli possono essere usati per richiedere che i parametri di tipo generico derivino da classi base quali MarshalByRefObject). Tuttavia, il .NET Framework non supporta tipi generici associati al contesto. Un tipo generico può derivare da ContextBoundObject, ma provare a creare un'istanza di quel tipo causa un TypeLoadException.

  • L'enumerazione non può avere parametri di tipo generico. Un'enumerazione può essere generica solo incidentalmente (ad esempio, perché è annidata in un tipo generico che viene definito con Visual Basic, C# o C++). Per altre informazioni, vedere "Enumerazioni" in Common Type System.

  • I metodi dinamici leggeri non possono essere generici.

  • In Visual Basic, C# e C++ non è possibile creare un'istanza di un tipo annidato in un tipo generico a meno che non siano stati assegnati i tipi ai parametri di tipo di tutti i tipi di inclusione. In altre parole, in una reflection un tipo annidato che viene definito con questi linguaggi contiene i parametri di tutti i relativi tipi di inclusione. Ciò consente di usare i parametri di tipo dei tipi in inclusione nelle definizioni di membro di un tipo annidato. Per altre informazioni, vedere "Tipi annidati" in MakeGenericType.

    System_CAPS_noteNota

    Un tipo annidato definito con la creazione di codice in un assembly dinamico o usando Ilasm.exe (IL Assembler) non deve includere i parametri di tipo dei relativi tipi di inclusione. Tuttavia, se non li include, i parametri di tipo non saranno nell'ambito della classe annidata.

    Per altre informazioni, vedere "Tipi annidati" in MakeGenericType.

Torna all'inizio

.NET Framework fornisce una serie di classi di raccolte generiche negli spazi dei nomi seguenti:

Nello spazio dei nomi System sono disponibili interfacce generiche per l'implementazione di confronti di uguaglianza e ordinamento, oltre ai tipi delegati generici per gestori eventi, conversioni e predicati di ricerca.

Il supporto dei generics è stato aggiunto allo spazio dei nomi System.Reflection per l'esame di tipi e metodi generici, a System.Reflection.Emit per la creazione di assembly dinamici che contengono tipi e metodi generici e a System.CodeDom per la generazione di grafici di origine che includono generics.

Il Common Language Runtime fornisce nuovi codici operativi e prefissi per supportare i tipi generici nel linguaggio MSIL (Microsoft Intermediate Language), inclusi Stelem, Ldelem, Unbox_Any, Constrained e Readonly.

Visual C++, C# e Visual Basic forniscono il supporto completo per la definizione e l'utilizzo dei generics. Per altre informazioni sul supporto dei linguaggi, vedere Tipi generici in Visual Basic (Visual Basic), Introduzione ai generics (Guida per programmatori C#) e Overview of Generics in Visual C++.

Torna all'inizio

Un tipo annidato all'interno di un tipo generico può dipendere dai parametri di tipo del tipo generico che lo contiene. Common Language Runtime considera i tipi annidati come generici, anche se non dispongono di propri parametri di tipo generico. Quando si crea un'istanza di un tipo annidato, è necessario specificare gli argomenti di tipo per tutti i tipi generici.

Torna all'inizio

Titolo

Descrizione

Raccolte generiche in .NET Framework

Vengono descritte le classi di raccolte generiche e altri tipi generici in .NET Framework.

Delegati generici per la modifica di matrici ed elenchi

Vengono descritti i delegati generici per conversioni, predicati di ricerca e azioni da eseguire sugli elementi di una matrice o raccolta.

Interfacce generiche

Vengono descritte le interfacce generiche che forniscono funzionalità comuni a famiglie di tipi generici.

Covarianza e controvarianza nei generics

Vengono descritte la covarianza e controvarianza nei parametri di tipo generico.

Tipi di raccolte comunemente utilizzate

Fornisce informazioni di riepilogo sulle caratteristiche e gli scenari di utilizzo dei tipi di raccolta in .NET Framework, inclusi i tipi generici.

Quando utilizzare raccolte generiche

Vengono descritte le regole generali per determinare quando usare i tipi di raccolte generiche.

How to: Define a Generic Type with Reflection Emit

Viene illustrato come generare assembly dinamici che includono tipi e metodi generici.

Tipi generici in Visual Basic (Visual Basic)

Viene descritta la funzionalità generics per gli utenti di Visual Basic, tra cui procedure relative all'utilizzo e alla definizione di tipi generici.

Introduzione ai generics (Guida per programmatori C#)

Viene fornita una panoramica di definizione e utilizzo di tipi generici per gli utenti di C#.

Overview of Generics in Visual C++

Viene descritta la funzionalità generics per gli utenti di C++, incluse le differenze tra generics e modelli.

Mostra: