Métodos genéricos (guía de programación de C#)

Un método genérico es un método que se declara con parámetros de tipo, de la manera siguiente:

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

En el siguiente ejemplo de código se muestra una manera de llamar al método con int para el argumento de tipo:

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

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

También puede omitir el argumento de tipo y el compilador lo deducirá. La siguiente llamada a Swap es equivalente a la llamada anterior:

Swap(ref a, ref b);

Las mismas reglas para la inferencia de tipos se aplican a los métodos estáticos y a los métodos de instancia. El compilador puede deducir los parámetros de tipo basados en los argumentos de método que se pasan; no puede deducir los parámetros de tipo solo desde un valor devuelto o una restricción. Por lo tanto, la inferencia de tipos no funciona con métodos que no tienen parámetros. La inferencia de tipos se produce en tiempo de compilación antes de que el compilador intente resolver las firmas de método sobrecargadas. El compilador aplica la lógica de inferencia de tipos a todos los métodos genéricos que comparten el mismo nombre. En el paso de resolución de sobrecarga, el compilador incluye solo esos métodos genéricos en los que la inferencia de tipos se ha realizado correctamente.

Dentro de una clase genérica, los métodos no genéricos pueden tener acceso a los parámetros de tipo de nivel de clase, de la manera siguiente:

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

Si define un método genérico que toma los mismos parámetros de tipo que la clase contenedora, el compilador genera la advertencia CS0693 porque, dentro del ámbito del método, el argumento que se ha proporcionado para el T interno oculta el argumento que se ha proporcionado para el T externo. Si necesita la flexibilidad de llamar a un método de la clase genérica con argumentos de tipo diferentes de los que se han proporcionado cuando se ha creado una instancia de la clase, considere la posibilidad de proporcionar otro identificador para el parámetro de tipo del método, como se muestra en GenericList2<T> en el ejemplo siguiente.

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

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

Use restricciones para permitir operaciones más especializadas en parámetros de tipo de métodos. Esta versión de Swap<T>, ahora denominada SwapIfGreater<T>, solo puede usarse con argumentos de tipo que implementan 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;
    }
}

Los métodos genéricos pueden sobrecargarse en varios parámetros de tipo. Por ejemplo, todos los métodos siguientes pueden ubicarse en la misma clase:

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

También puede usar el parámetro de tipo como tipo de valor devuelto de un método. En el ejemplo de código siguiente se muestra un método que devuelve una matriz de tipo T:

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

Especificación del lenguaje C#

Para obtener más información, consulte la Especificación del lenguaje C#.

Consulte también