C# Academy · Lezione

Interfacce generiche

Astragga rispetto ai tipi.

Lezione 4 di 413 passaggi

Interfacce generiche è una lezione C# Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento C# Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso C# Academy include 4 lezioni in totale.

Che cos'è un'interfaccia generica?

Un'interfaccia generica dichiara i parametri di tipo tra parentesi angolari dopo il proprio nome. Chi la implementa sceglie i tipi concreti e il contratto dell'interfaccia si adatta di conseguenza.

La libreria .NET le utilizza ovunque, ad esempio IEnumerable<T> e IComparable<T>.

interface IRepository<T>
{
    void Add(T item);
    T Get(int id);
}

Implementare un'interfaccia generica

Una classe può implementare un'interfaccia generica fornendo un argomento di tipo concreto. Le firme dei metodi utilizzano quindi quel tipo reale.

Si ottiene così un contratto riutilizzabile e tipizzato in modo sicuro, senza conversioni di tipo.

using System.Collections.Generic;

class IntStore : IRepository<int>
{
    private readonly List<int> data = new();
    public void Add(int item) => data.Add(item);
    public int Get(int id) => data[id];
}

interface IRepository<T>
{
    void Add(T item);
    T Get(int id);
}

Mantenere la genericità nell'implementazione

Una classe può implementare un'interfaccia generica rimanendo a sua volta generica e inoltrando il proprio parametro di tipo all'interfaccia.

In questo modo l'implementazione rimane riutilizzabile per qualsiasi tipo di elemento.

using System.Collections.Generic;

class Store<T> : IRepository<T>
{
    private readonly List<T> data = new();
    public void Add(T item) => data.Add(item);
    public T Get(int id) => data[id];
}

interface IRepository<T> { void Add(T item); T Get(int id); }

IComparable<T> in azione

IComparable<T> è un'interfaccia generica integrata. Implementandola, il tipo può definire l'ordinamento delle proprie istanze, rendendo possibile l'ordinamento.

Il metodo CompareTo restituisce un valore negativo, zero oppure un valore positivo.

class Money : IComparable<Money>
{
    public int Cents;
    public int CompareTo(Money? other)
        => Cents.CompareTo(other?.Cents ?? 0);
}

Implementare IEnumerable<T>

IEnumerable<T> è alla base di LINQ e di foreach. Un tipo che la implementa può essere attraversato. Spesso si delega l'iterazione all'iteratore di una raccolta interna.

I metodi iteratore con yield return rendono tutto questo semplice.

using System.Collections;
using System.Collections.Generic;

class Bag<T> : IEnumerable<T>
{
    private readonly List<T> items = new();
    public void Add(T x) => items.Add(x);
    public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

Un'interfaccia generica eseguibile

Questo programma completo definisce IPrinter<T>, un'interfaccia generica, la implementa per le stringhe e la utilizza.

L'interfaccia garantisce la presenza di un metodo Print, indipendentemente dal tipo concreto.

using System;

interface IPrinter<T> { void Print(T value); }

class ConsolePrinter<T> : IPrinter<T>
{
    public void Print(T value) => Console.WriteLine(value);
}

class Program
{
    static void Main()
    {
        IPrinter<string> p = new ConsolePrinter<string>();
        p.Print("hello generics");
    }
}

Covarianza con out

Un parametro di un'interfaccia generica contrassegnato con out è covariante: compare solo nelle posizioni di output. Ciò consente di utilizzare IEnumerable<Cat> dove è previsto IEnumerable<Animal>.

La covarianza mantiene la compatibilità delle assegnazioni lungo una gerarchia di ereditarietà.

interface IProducer<out T>
{
    T Produce();
}

Controvarianza con in

Un parametro contrassegnato con in è controvariante: compare solo nelle posizioni di input. Ciò consente di utilizzare un IComparer<Animal> dove è richiesto un IComparer<Cat>.

La controvarianza inverte la direzione dell'assegnabilità per i consumer.

interface IConsumer<in T>
{
    void Consume(T item);
}

Più parametri di tipo

Le interfacce generiche possono accettare più di un parametro. IDictionary<TKey, TValue> è un esempio noto, con tipi distinti per chiave e valore.

Ogni parametro può essere indipendentemente invariante, covariante o controvariante.

interface IMapper<TIn, TOut>
{
    TOut Map(TIn input);
}

Programmare in base all'interfaccia

Dipendere da un'interfaccia generica anziché da una classe concreta rende il codice flessibile. È possibile sostituire le implementazioni senza modificare il codice chiamante.

I parametri dei metodi tipizzati come IEnumerable<T> accettano indifferentemente liste, matrici e risultati di query.

using System.Collections.Generic;
using System.Linq;

int Total(IEnumerable<int> values) => values.Sum();

Vincoli che usano interfacce generiche

Le interfacce generiche vengono spesso usate come vincoli. where T : IComparable<T> consente a un metodo di ordinare o confrontare i propri input.

In questo modo si combinano due funzionalità dei generics per creare algoritmi sicuri e riutilizzabili.

T Min<T>(T a, T b) where T : IComparable<T>
    => a.CompareTo(b) <= 0 ? a : b;

Verifica rapida

Verifichi la Sua comprensione delle interfacce generiche.

Riepilogo

Le interfacce generiche dichiarano parametri di tipo e consentono alle implementazioni di specificarli o propagarli. Tra gli esempi incorporati troviamo IEnumerable<T>, IComparable<T> e IDictionary<TKey, TValue>.

Le annotazioni di varianza out e in abilitano covarianza e controvarianza, mentre le interfacce generiche si abbinano naturalmente ai vincoli where.

Gratis per iniziare

Impara C# con un tutor IA — gratis

Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.

Corsi
93
Lezioni
346

Domande Frequenti

La lezione «Interfacce generiche» è gratuita?

Sì — il testo completo di «Interfacce generiche» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso C# Academy, passa a CoddyKit PRO. Il corso C# Academy include 4 lezioni in totale.

Cosa imparerò in «Interfacce generiche»?

Astragga rispetto ai tipi. Eserciti C# Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare C# Academy?

Non è richiesta alcuna esperienza precedente. C# Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Interfacce generiche»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione C# Academy?

Sì. Ogni lezione C# Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Metodi generici
  2. Classi generiche
  3. Vincoli where
  4. Interfacce generiche
← Torna a C# Academy