In C#, i generics sono una funzionalità avanzata del linguaggio che consente di scrivere classi, metodi, interfacce, delegati o strutture che operano su tipi specificati dall’utente senza dover definire ogni volta il tipo esatto. L’obiettivo principale dei generics è di migliorare la riutilizzabilità del codice, la sicurezza dei tipi (type safety) e le prestazioni.
Se sviluppi delle classi generiche come ad esempio un Adapter a MongoDb oppure una libreria che per leggere email da un server, l’uso dei generics rende il tuo codice leggibile, leggero ed estendibile.
https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/types/generics
Concetti di base
I generics permettono di definire un contenitore o un’operazione che non è vincolata a un tipo specifico fino a quando non viene utilizzata. Ad esempio, anziché creare una classe che funziona solo con int
o string
, puoi definire una classe generica che funziona con qualsiasi tipo.
Vediamo un esempio di classe generica
public class MyGenericClass<T>
{
public T Value { get; set; }
public void DisplayValue()
{
Console.WriteLine($"Il valore è: {Value}");
}
}
In questo caso, T
è un parametro di tipo generico che verrà sostituito con un tipo specifico quando la classe verrà utilizzata.
Esempi pratici
Vediamo alcuni semplici esempi pratici per capire meglio la funzionalità.
var intInstance = new MyGenericClass<int>();
intInstance.Value = 10;
intInstance.DisplayValue();
var stringInstance = new MyGenericClass<string>();
stringInstance.Value = "Ciao";
stringInstance.DisplayValue();
Il valore è: 10
Il valore è: Ciao
Usiamo ora dei metodi generici
public void Print<T>(T data)
{
Console.WriteLine($"Dato: {data}");
}
// Uso
Print(123); // Output: Dato: 123
Print("Test"); // Output: Dato: Test
I generics sono utilizzati ad esempio nelle librerie standard: (System.Collections.Generic
), come List<T>
, Dictionary<TKey, TValue>
, Queue<T>
, e molte altre.
Alcuni esempi:
List<int> numbers = new List<int> { 1, 2, 3, 4 };
numbers.Add(5);
Console.WriteLine(numbers[2]); // Output: 3
Vantaggi dei Generics
- Sicurezza dei tipi:
- Permettono di lavorare con tipi fortemente tipizzati senza casting espliciti.
- Errori di tipo vengono rilevati in fase di compilazione.
- Riutilizzabilità del codice:
- Si evita di riscrivere codice per tipi diversi.
- Una sola implementazione generica funziona con qualsiasi tipo.
- Prestazioni:
- Evitano il boxing/unboxing nei tipi valore.
- Sono più efficienti rispetto a soluzioni basate su oggetti generici come
ArrayList
.
Vincoli sui Generics
C# consente di applicare vincoli sui parametri di tipo per specificare i requisiti che il tipo deve soddisfare:
where T : class
→ il tipo deve essere una classe.where T : struct
→ il tipo deve essere un valore.where T : new()
→ il tipo deve avere un costruttore pubblico predefinito.where T : BaseClass
→ il tipo deve derivare da una classe specifica.
ad esempio:
public class MyGenericClass<T> where T : class, new()
{
public T CreateInstance()
{
return new T();
}
}
Per concludere
I generics rappresentano una potente funzionalità di C# per creare codice flessibile, sicuro e riutilizzabile. Collections generiche come List<T>
e Dictionary<TKey, TValue>
sono esempi comuni che mostrano come i generics siano centrali nello sviluppo moderno in C#.
Nei prossimi articoli descriverò un uso più avanzato dei generics mostrando una libreria base sviluppata come adapter per accedere e scrivere su Mongo Db.