Métodos genéricos (Guia de Programação em C#)
Um método genérico é um método declarado com parâmetros de tipo, da seguinte maneira:
static void Swap<T>(ref T lhs, ref T rhs)
{
T temp;
temp = lhs;
lhs = rhs;
rhs = temp;
}
O exemplo de código a seguir mostra uma maneira de chamar o método usando int
para o argumento de tipo:
public static void TestSwap()
{
int a = 1;
int b = 2;
Swap<int>(ref a, ref b);
System.Console.WriteLine(a + " " + b);
}
Também é possível omitir o argumento de tipo e o compilador o inferirá. Esta chamada para Swap
é equivalente à chamada anterior:
Swap(ref a, ref b);
As mesmas regras de inferência de tipos se aplicam a métodos estáticos e métodos de instância. O compilador pode inferir os parâmetros de tipo com base nos argumentos de método passados; não é possível inferir os parâmetros de tipo somente de uma restrição ou valor retornado. Portanto, a inferência de tipos não funciona com métodos que não têm parâmetros. A inferência de tipos ocorre em tempo de compilação, antes de o compilador tentar resolver assinaturas de método sobrecarregadas. O compilador aplica a lógica da inferência de tipos a todos os métodos genéricos que compartilham o mesmo nome. Na etapa de resolução de sobrecarga, o compilador incluirá somente os métodos genéricos em que a inferência de tipos foi bem-sucedida.
Em uma classe genérica, métodos não genéricos podem acessar os parâmetros de tipo de nível de classe, da seguinte maneira:
class SampleClass<T>
{
void Swap(ref T lhs, ref T rhs) { }
}
Se um método genérico que usa os mesmos parâmetros de tipo da classe que o contém for definido, o compilador gerará um aviso CS0693, pois, dentro do escopo do método, o argumento fornecido para o T
interno oculta o argumento fornecido para o T
externo. Caso seja necessária a flexibilidade de chamar um método de classe genérica com argumentos de tipo diferentes dos fornecidos quando a instância da classe foi criada, considere fornecer outro identificador ao parâmetro de tipo do método, conforme mostrado no GenericList2<T>
do exemplo a seguir.
class GenericList<T>
{
// CS0693.
void SampleMethod<T>() { }
}
class GenericList2<T>
{
// No warning.
void SampleMethod<U>() { }
}
Use restrições para permitir operações mais especializadas em parâmetros de tipo de métodos. Essa versão do Swap<T>
, agora denominada SwapIfGreater<T>
, pode ser usada somente com argumentos de tipo que implementam 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;
}
}
Métodos genéricos podem ser sobrecarregados vários parâmetros de tipo. Por exemplo, todos os seguintes métodos podem ser localizados na mesma classe:
void DoWork() { }
void DoWork<T>() { }
void DoWork<T, U>() { }
Você também pode usar o parâmetro de tipo como o tipo de retorno de um método. O exemplo de código a seguir mostra um método que retorna uma matriz de tipo T
:
T[] Swap<T>(T a, T b)
{
return [b, a];
}
Especificação da Linguagem C#
Para obter mais informações, consulte a Especificação da linguagem C#.