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

Confira também