Поделиться через


Универсальные классы и методы

Универсальные шаблоны представляют концепцию параметров типа в .NET. Универсальные шаблоны позволяют создавать классы и методы, откладывающие спецификацию одного или нескольких параметров типа, пока не будет использоваться класс или метод в коде. Как пример, ниже показан класс с параметром T универсального типа. Этот класс может использоваться в другом клиентском коде, не требуя ресурсов и не создавая рисков, связанных с операциями приведения и упаковки-преобразования в среде выполнения.

// Declare the generic class.
public class GenericList<T>
{
    public void Add(T item) { }
}

public class ExampleClass { }

class TestGenericList
{
    static void Main()
    {
        // Create a list of type int.
        GenericList<int> list1 = new();
        list1.Add(1);

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

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

Универсальные классы и методы объединяют повторное использование, безопасность типов и эффективность таким образом, что их негенерические аналоги не могут. Параметры универсального типа заменяются аргументами типа во время компиляции. В предыдущем примере компилятор заменяет T intего. Универсальные типы наиболее часто используются с коллекциями и методами, которые выполняют с ними операции. Пространство имен System.Collections.Generic содержит несколько универсальных классов коллекций. Негенерические коллекции, такие как ArrayList не рекомендуется и поддерживаются только в целях совместимости. Дополнительные сведения см. в статье об универсальных шаблонах в .NET.

Вы также можете создать пользовательские универсальные типы и методы, чтобы предоставить собственные обобщенные решения и шаблоны проектирования, которые являются типобезопасными и эффективными. В следующем примере кода показан простой универсальный класс связанного списка для демонстрационных целей. (В большинстве случаев следует использовать класс, предоставленный List<T> .NET, вместо создания собственного.) Параметр T типа используется в нескольких расположениях, где конкретный тип обычно используется для указания типа элемента, хранящегося в списке:

  • в качестве типа параметра метода в методе AddHead;
  • в качестве типа возвращаемого значения свойства Data во вложенном классе Node;
  • в качестве типа закрытого члена data во вложенном классе.

T доступен для вложенного Node класса. При GenericList<T> создании экземпляра с конкретным типом, например как, GenericList<int>каждое вхождение T заменяется intна .

// Type parameter T in angle brackets.
public class GenericList<T>
{
    // The nested class is also generic, and
    // holds a data item of type T.
    private class Node(T t)
    {
        // T as property type.
        public T Data { get; set; } = t;

        public Node? Next { get; set; }
    }

    // First item in the linked list
    private Node? head;

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

    // T in method return type.
    public IEnumerator<T> GetEnumerator()
    {
        Node? current = head;

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

В следующем примере кода показано, как клиентский код использует универсальный класс GenericList<T> для создания списка целых чисел. При изменении аргумента типа следующий код создает списки строк или любого другого пользовательского типа:

// A generic list of int.
GenericList<int> list = new();

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

// Write them to the console.
foreach (int i in list)
{
    Console.WriteLine(i);
}

Console.WriteLine("Done");

Примечание.

Универсальные типы не ограничиваются классами. В предыдущих примерах используются class типы, но можно определить универсальные interface и struct типы, включая record типы.

Общие сведения об универсальных шаблонах

  • Используйте универсальные типы, чтобы получить максимально широкие возможности многократного использования кода, обеспечения безопасности типов и повышения производительности.
  • Чаще всего универсальные шаблоны используются для создания классов коллекций.
  • Библиотека классов .NET содержит несколько универсальных классов коллекций в пространстве имен System.Collections.Generic. Универсальные коллекции следует использовать всякий раз, когда это возможно, вместо классов, таких как ArrayList в System.Collections пространстве имен.
  • Вы можете создавать собственные универсальные интерфейсы, классы, методы, события и делегаты.
  • Универсальные классы можно ограничить, чтобы обеспечить доступ к методам для определенных типов данных.
  • Вы можете получить сведения во время выполнения о типах, используемых в универсальном типе данных, с помощью отражения.

Спецификация языка C#

Дополнительные сведения см. в спецификации языка C#.

См. также