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#.