Clases y métodos genéricos

Los genéricos presentan el concepto de parámetros de tipo en .NET, lo que permite diseñar clases y métodos que aplazan la especificación de uno o varios tipos hasta que el código de cliente declara y crea instancias de la clase o método. Por ejemplo, al usar un parámetro de tipo genérico T, puede escribir una clase única que otro código de cliente puede usar sin incurrir en el costo o riesgo de conversiones en tiempo de ejecución u operaciones de conversión boxing, como se muestra aquí:

// Declare the generic class.
public class GenericList<T>
{
    public void Add(T input) { }
}
class TestGenericList
{
    private class ExampleClass { }
    static void Main()
    {
        // Declare a list of type int.
        GenericList<int> list1 = new GenericList<int>();
        list1.Add(1);

        // Declare a list of type string.
        GenericList<string> list2 = new GenericList<string>();
        list2.Add("");

        // Declare a list of type ExampleClass.
        GenericList<ExampleClass> list3 = new GenericList<ExampleClass>();
        list3.Add(new ExampleClass());
    }
}

Las clases y métodos genéricos combinan reusabilidad, seguridad de tipos y eficacia de una manera en que sus homólogos no genéricos no pueden. Los genéricos se usan frecuentemente con colecciones y los métodos que funcionan en ellas. El espacio de nombres System.Collections.Generic contiene varias clases de colecciones basadas en genéricos. No se recomiendan las colecciones no genéricas, como ArrayList, y se mantienen por compatibilidad. Para más información, vea Elementos genéricos en .NET.

También puede crear métodos y tipos genéricos personalizados para proporcionar sus propias soluciones generalizadas y patrones de diseño que sean seguros para tipos y eficaces. En el ejemplo de código siguiente se muestra una clase genérica simple de lista vinculada para fines de demostración. (En la mayoría de los casos, debe usar la clase List<T> proporcionada por .NET en lugar de crear la suya propia). El parámetro de tipo T se usa en diversas ubicaciones donde normalmente se usaría un tipo concreto para indicar el tipo del elemento almacenado en la lista. Se usa de estas formas:

  • Como el tipo de un parámetro de método en el método AddHead.
  • Como el tipo de valor devuelto de la propiedad Data en la clase anidada Node.
  • Como el tipo de miembro privado data de la clase anidada.

T está disponible para la clase Node anidada. Cuando se crea una instancia de GenericList<T> con un tipo concreto, por ejemplo como un GenericList<int>, cada repetición de T se sustituye por int.

// type parameter T in angle brackets
public class GenericList<T>
{
    // The nested class is also generic on T.
    private class Node
    {
        // T used in non-generic constructor.
        public Node(T t)
        {
            next = null;
            data = t;
        }

        private Node? next;
        public Node? Next
        {
            get { return next; }
            set { next = value; }
        }

        // T as private member data type.
        private T data;

        // T as return type of property.
        public T Data
        {
            get { return data; }
            set { data = value; }
        }
    }

    private Node? head;

    // constructor
    public GenericList()
    {
        head = null;
    }

    // T as method parameter type:
    public void AddHead(T t)
    {
        Node n = new Node(t);
        n.Next = head;
        head = n;
    }

    public IEnumerator<T> GetEnumerator()
    {
        Node? current = head;

        while (current != null)
        {
            yield return current.Data;
            current = current.Next;
        }
    }
}

En el ejemplo de código siguiente se muestra cómo el código de cliente usa la clase genérica GenericList<T> para crear una lista de enteros. Simplemente cambiando el argumento de tipo, el código siguiente puede modificarse fácilmente para crear listas de cadenas o cualquier otro tipo personalizado:

class TestGenericList
{
    static void Main()
    {
        // int is the type argument
        GenericList<int> list = new GenericList<int>();

        for (int x = 0; x < 10; x++)
        {
            list.AddHead(x);
        }

        foreach (int i in list)
        {
            System.Console.Write(i + " ");
        }
        System.Console.WriteLine("\nDone");
    }
}

Introducción a los genéricos

  • Use tipos genéricos para maximizar la reutilización del código, la seguridad de tipos y el rendimiento.
  • El uso más común de los genéricos es crear clases de colección.
  • La biblioteca de clases de .NET contiene varias clases de colección genéricas en el espacio de nombres System.Collections.Generic. Las colecciones genéricas se deben usar siempre que sea posible en lugar de clases como en ArrayList el espacio de System.Collections nombres .
  • Puede crear sus propias interfaces, clases, métodos, eventos y delegados genéricos.
  • Puede limitar las clases genéricas para habilitar el acceso a métodos en tipos de datos determinados.
  • Puede obtener información sobre los tipos que se usan en un tipo de datos genérico en tiempo de ejecución mediante la reflexión.

Especificación del lenguaje C#

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

Vea también