Metodi generici (Guida per programmatori C#)

Un metodo generico è un metodo che viene dichiarato con parametri di tipo, in questo modo:

static void Swap<T>(ref T lhs, ref T rhs)
{
    T temp;
    temp = lhs;
    lhs = rhs;
    rhs = temp;
}

L'esempio di codice seguente mostra un modo per chiamare il metodo usando int per l'argomento tipo:

public static void TestSwap()
{
    int a = 1;
    int b = 2;

    Swap<int>(ref a, ref b);
    System.Console.WriteLine(a + " " + b);
}

È anche possibile omettere l'argomento tipo perché venga dedotto dal compilatore. La chiamata seguente a Swap equivale alla chiamata precedente:

Swap(ref a, ref b);

Ai metodi statici e ai metodi di istanza si applicano le stesse regole relative all'inferenza del tipo. Il compilatore può dedurre i parametri di tipo in base agli argomenti metodo passati, ma non può dedurli solo da un vincolo o da un valore restituito. Di conseguenza, l'inferenza del tipo non funziona con metodi che non includono parametri. L'inferenza del tipo avviene in fase di compilazione prima che il compilatore provi a risolvere le firme dei metodi di overload. Il compilatore applica la logica di inferenza del tipo a tutti i metodi generici che condividono lo stesso nome. Nel passaggio di risoluzione dell'overload, il compilatore include solo i metodi generici per cui l'inferenza del tipo è riuscita.

All'interno di una classe generica metodi non generici possono accedere ai parametri di tipo a livello di classe, in questo modo:

class SampleClass<T>
{
    void Swap(ref T lhs, ref T rhs) { }
}

Se si definisce un metodo generico che accetta gli stessi parametri di tipo della classe che lo contiene, il compilatore genera l'avviso CS0693 perché nell'ambito del metodo l'argomento specificato per il parametro T interno nasconde l'argomento specificato per il parametro T esterno. Se è necessaria la flessibilità di poter chiamare un metodo di una classe generica con argomenti tipo diversi da quelli specificati alla creazione di un'istanza della classe, provare a specificare un altro identificatore per il parametro di tipo del metodo, come mostrato in GenericList2<T> nell'esempio seguente.

class GenericList<T>
{
    // CS0693.
    void SampleMethod<T>() { }
}

class GenericList2<T>
{
    // No warning.
    void SampleMethod<U>() { }
}

Usare vincoli per consentire operazioni più specializzate sui parametri di tipo nei metodi. Questa versione di Swap<T>, ora chiamata SwapIfGreater<T>, può essere usata solo con argomenti tipo che implementano IComparable<T>.

void SwapIfGreater<T>(ref T lhs, ref T rhs) where T : System.IComparable<T>
{
    T temp;
    if (lhs.CompareTo(rhs) > 0)
    {
        temp = lhs;
        lhs = rhs;
        rhs = temp;
    }
}

È possibile eseguire l'overload di metodi generici in diversi parametri di tipo. Ad esempio, i metodi seguenti possono essere contenuti tutti nella stessa classe:

void DoWork() { }
void DoWork<T>() { }
void DoWork<T, U>() { }

È anche possibile usare il parametro di tipo come tipo restituito di un metodo. L'esempio di codice seguente illustra un metodo che restituisce una matrice di tipo T:

T[] Swap<T>(T a, T b)
{
    return [b, a];
}

Specifiche del linguaggio C#

Per altre informazioni, vedere la specifica del linguaggio C#.

Vedi anche