Menu
Coddy logo textTech

Tipi generici (classi e metodi)

Fa parte della sezione Programmazione orientata agli oggetti del percorso C# di Coddy. Lezione 42 di 70.

I generics ti permettono di scrivere classi e metodi che funzionano con qualsiasi tipo di dato mantenendo la sicurezza dei tipi. Invece di scrivere classi separate per IntList, StringList e DoubleList, scrivi un’unica classe generica che li gestisce tutti.

Una classe generica usa un parametro di tipo, in genere chiamato T, racchiuso tra parentesi angolari:

public class Box<T>
{
    private T content;
    
    public void Store(T item) => content = item;
    public T Retrieve() => content;
}

// Utilizzo con tipi diversi
Box<int> intBox = new Box<int>();
intBox.Store(42);

Box<string> stringBox = new Box<string>();
stringBox.Store("Hello");

Quando crei Box<int>, il compilatore sostituisce ogni T con int. Questo fornisce un controllo dei tipi in fase di compilazione: non puoi memorizzare accidentalmente una stringa in un contenitore int.

I metodi generici funzionano in modo simile e consentono a un singolo metodo di operare su tipi diversi:

public static void Swap<T>(ref T a, ref T b)
{
    T temp = a;
    a = b;
    b = temp;
}

int x = 1, y = 2;
Swap(ref x, ref y);  // x=2, y=1

Il compilatore deduce il tipo dagli argomenti, quindi non devi scrivere esplicitamente Swap<int>. I generics sono alla base di collezioni come List<T> e Dictionary<TKey, TValue> e consentono di scrivere codice riutilizzabile e sicuro rispetto ai tipi.

challenge icon

Sfida

Facile

Creiamo un sistema generico Storage<T> in grado di contenere e gestire elementi di qualsiasi tipo. Creerai una classe contenitore riutilizzabile che dimostra la potenza dei generics: scrivila una volta e usala con interi, stringhe o qualsiasi altro tipo!

Organizzerai il codice in due file:

  • Storage.cs: crea una classe generica Storage<T> nello spazio dei nomi DataStorage. Il contenitore deve:
    • Avere un array privato di tipo T per contenere gli elementi e una proprietà Count che tiene traccia del numero di elementi memorizzati
    • Accettare una capacità nel costruttore per inizializzare l'array interno
    • Avere un metodo Add(T item) che aggiunge un elemento se c'è spazio
    • Avere un metodo Get(int index) che restituisce l'elemento all'indice specificato
    • Avere un metodo GetAll() che restituisce tutti gli elementi memorizzati, uniti da ", "
  • Program.cs: nel file principale, mostra la tua classe generica in funzione con due tipi diversi. Crea una Storage<int> e una Storage<string>, aggiungi elementi a ciascuna e mostra che la stessa classe funziona senza problemi con entrambi i tipi.

Riceverai quattro input:

  • Primo intero da memorizzare
  • Secondo intero da memorizzare
  • Prima stringa da memorizzare
  • Seconda stringa da memorizzare

Crea un contenitore di interi con capacità 5 e un contenitore di stringhe con capacità 5. Aggiungi i due interi al contenitore di interi e le due stringhe al contenitore di stringhe.

Stampa l'output in questo formato:

Int storage: {GetAll()}
Int count: {Count}
First int: {Get(0)}
String storage: {GetAll()}
String count: {Count}
First string: {Get(0)}

Per esempio, se gli input sono 42, 100, Hello e World, l'output dovrebbe essere:

Int storage: 42, 100
Int count: 2
First int: 42
String storage: Hello, World
String count: 2
First string: Hello

Nota che scrivi la classe Storage<T> una sola volta, ma funziona perfettamente sia con int che con string: questa è la magia dei generics! Il compilatore garantisce la sicurezza dei tipi, così non puoi aggiungere accidentalmente una stringa al contenitore di interi.

Provalo tu

using System;
using DataStorage;

class Program
{
    public static void Main(string[] args)
    {
        // Leggi gli input
        int num1 = Convert.ToInt32(Console.ReadLine());
        int num2 = Convert.ToInt32(Console.ReadLine());
        string str1 = Console.ReadLine();
        string str2 = Console.ReadLine();

        // TODO: Crea uno Storage<int> con capacità 5
        
        // TODO: Aggiungi i due numeri interi allo storage degli interi
        
        // TODO: Crea uno Storage<string> con capacità 5
        
        // TODO: Aggiungi le due stringhe allo storage delle stringhe
        
        // TODO: Stampa l'output nel formato richiesto
        // Int storage: {GetAll()}
        // Conteggio degli interi: {Count}
        // Primo intero: {Get(0)}
        // String storage: {GetAll()}
        // String count: {Count}
        // First string: {Get(0)}
    }
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore C# online