Classes e métodos genéricos

Generics introduz o conceito de parâmetros de tipo para .NET. Os genéricos possibilitam o design de classes e métodos que adiam a especificação de um ou mais parâmetros de tipo até que você use a classe ou o método em seu código. Por exemplo, usando um parâmetro Tde tipo genérico , você pode escrever uma única classe que outro código de cliente pode usar sem incorrer no custo ou risco de transmissões de tempo de execução ou operações de boxe, conforme mostrado aqui:

// 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());
    }
}

As classes e métodos genéricos combinam reutilização, segurança de tipo e eficiência de uma forma que os seus homólogos não genéricos não conseguem. Os parâmetros de tipo genéricos são substituídos pelos argumentos de tipo durante a compilação. No exemplo anterior, o compilador substitui T por int. Os genéricos são mais frequentemente utilizados com as coleções e os métodos que nelas operam. O System.Collections.Generic namespace contém várias classes de coleção baseadas em genérico. As coleções não genéricas, como ArrayList não são recomendadas e são mantidas apenas para fins de compatibilidade. Para obter mais informações, consulte Genéricos no .NET.

Você também pode criar tipos e métodos genéricos personalizados para fornecer suas próprias soluções generalizadas e padrões de design que são seguros para tipos e eficientes. O exemplo de código a seguir mostra uma classe de lista vinculada genérica simples para fins de demonstração. (Na maioria dos casos, você deve usar a classe fornecida pelo .NET em vez de criar a List<T> sua própria.) O parâmetro T type é usado em vários locais onde um tipo concreto normalmente seria usado para indicar o tipo do item armazenado na lista:

  • Como o tipo de um parâmetro de método no AddHead método.
  • Como o tipo de retorno da Data propriedade na classe aninhada Node .
  • Como o tipo do membro data privado na classe aninhada.

T está disponível para a classe aninhada Node . Quando GenericList<T> é instanciado com um tipo concreto, por exemplo, como um GenericList<int>, cada ocorrência de é substituída T 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;
        }
    }
}

O exemplo de código a seguir mostra como o código do cliente usa a classe genérica GenericList<T> para criar uma lista de inteiros. Se você alterar o argumento type, o código a seguir criará listas de cadeias de caracteres ou qualquer outro 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");
    }
}

Nota

Os tipos genéricos não se limitam às classes. Os exemplos anteriores usam class tipos, mas você pode definir genéricos interface e struct tipos, incluindo record tipos.

Visão geral dos genéricos

  • Use tipos genéricos para maximizar a reutilização de código, a segurança de tipos e o desempenho.
  • O uso mais comum de genéricos é criar classes de coleção.
  • A biblioteca de classes .NET contém várias classes de coleção genéricas no System.Collections.Generic namespace. As coleções genéricas devem ser usadas sempre que possível em vez de classes como ArrayList no System.Collections namespace.
  • Você pode criar suas próprias interfaces genéricas, classes, métodos, eventos e delegados.
  • As classes genéricas podem ser restringidas para permitir o acesso a métodos em tipos de dados específicos.
  • Você pode obter informações em tempo de execução sobre os tipos que são usados em um tipo de dados genérico usando reflexão.

Especificação da linguagem C#

Para obter mais informações, consulte a Especificação da linguagem C#.

Consulte também