Classi e metodi generici
Generics introduce il concetto di parametri di tipo in .NET. I generics consentono di progettare classi e metodi che rinviano la specifica di uno o più parametri di tipo fino a quando non si usa la classe o il metodo nel codice. Ad esempio, usando un parametro di tipo generico T
è possibile scrivere un'unica classe che altro codice client può usare senza rischiare cast di runtime o operazioni di conversione boxing, come illustrato di seguito:
// Declare the generic class.
public class GenericList<T>
{
public void Add(T item) { }
}
public class ExampleClass { }
class TestGenericList
{
static void Main()
{
// Create a list of type int.
GenericList<int> list1 = new();
list1.Add(1);
// Create a list of type string.
GenericList<string> list2 = new();
list2.Add("");
// Create a list of type ExampleClass.
GenericList<ExampleClass> list3 = new();
list3.Add(new ExampleClass());
}
}
Le classi e i metodi generici combinano riutilizzabilità, sicurezza dei tipi ed efficienza in modo che le controparti non generiche non possano. I parametri di tipo generico vengono sostituiti con gli argomenti di tipo durante la compilazione. Nell'esempio precedente il compilatore sostituisce T
con int
. I generics sono in genere usati con le raccolte e i metodi che operano su di essi. Lo spazio dei nomi System.Collections.Generic contiene diverse classi di raccolta generiche. Le raccolte non generiche, ad esempio ArrayList non sono consigliate e vengono mantenute solo a scopo di compatibilità. Per altre informazioni, vedere Generics in .NET.
È anche possibile creare tipi e metodi generici personalizzati per offrire le proprie soluzioni e schemi progettuali generalizzati che sono indipendenti dai tipi ed efficienti. Nell'esempio di codice riportato di seguito viene illustrata una classe di elenco collegato generica semplice a scopo dimostrativo. Nella maggior parte dei casi, è consigliabile usare la List<T> classe fornita da .NET anziché crearne di personalizzate. Il parametro T
di tipo viene usato in diverse posizioni in cui in genere viene usato un tipo concreto per indicare il tipo dell'elemento archiviato nell'elenco:
- Come tipo di un parametro del metodo nel metodo
AddHead
. - Come tipo restituito della proprietà
Data
nella classeNode
annidata. - Come tipo del membro privato
data
nella classe annidata.
T
è disponibile per la classe Node
annidata. Quando GenericList<T>
viene creata un'istanza con un tipo concreto, ad esempio come GenericList<int>
, ogni occorrenza di T
viene sostituita con int
.
// Type parameter T in angle brackets.
public class GenericList<T>
{
// The nested class is also generic, and
// holds a data item of type T.
private class Node(T t)
{
// T as property type.
public T Data { get; set; } = t;
public Node? Next { get; set; }
}
// First item in the linked list
private Node? head;
// T as parameter type.
public void AddHead(T t)
{
Node n = new(t);
n.Next = head;
head = n;
}
// T in method return type.
public IEnumerator<T> GetEnumerator()
{
Node? current = head;
while (current is not null)
{
yield return current.Data;
current = current.Next;
}
}
}
Nell'esempio di codice riportato di seguito viene illustrato come il codice client usa la classe generica GenericList<T>
per creare un elenco di interi. Se si modifica l'argomento di tipo, il codice seguente crea elenchi di stringhe o qualsiasi altro tipo personalizzato:
// A generic list of int.
GenericList<int> list = new();
// Add ten int values.
for (int x = 0; x < 10; x++)
{
list.AddHead(x);
}
// Write them to the console.
foreach (int i in list)
{
Console.WriteLine(i);
}
Console.WriteLine("Done");
Nota
I tipi generici non sono limitati alle classi. Gli esempi precedenti usano class
tipi, ma è possibile definire tipi e struct
genericiinterface
, inclusi record
i tipi.
Panoramica sui generics
- Usare i tipi generici per ottimizzare il riutilizzo del codice, l'indipendenza dai tipi e le prestazioni.
- L'uso più comune dei generics consiste nel creare classi di raccolte.
- La libreria di classi .NET contiene diverse classi di raccolte generiche nello spazio dei nomi System.Collections.Generic. Queste raccolte generiche devono essere usate ogni volta che sia possibile al posto di classi come ArrayList nello spazio dei nomi System.Collections.
- È possibile creare interfacce, classi, metodi, eventi e delegati generici.
- Le classi generiche possono essere vincolate per consentire l'accesso ai metodi in tipi di dati specifici.
- È possibile ottenere informazioni in fase di esecuzione sui tipi usati in un tipo di dati generico tramite reflection.
Specifiche del linguaggio C#
Per altre informazioni, vedere la specifica del linguaggio C#.