Универсальные типы во время выполнения (руководство по программированию в C#)

Обновлен: Ноябрь 2007

При компиляции универсального типа или метода в код MSIL (Microsoft intermediate language — промежуточный язык Майкрософт), он содержит метаданные, указывающие, что он имеет параметры типа. Использование кода MSIL для универсального типа зависит от того, какой тип имеет поставляемый параметр типа — тип значения или ссылочный тип.

При первом построении универсального типа с типом значения в качестве параметра среда выполнения создает специализированный универсальный тип с поставляемым параметром или параметрами, которые замещаются в соответствующих местах кода MSIL. Специализированные универсальные типы создаются один раз для каждого уникального типа значения, который используется в качестве параметра.

Например, предположим, что в коде программы объявлен стек, построенный из целых чисел:

Stack<int> stack;

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

Stack<int> stackOne = new Stack<int>();
Stack<int> stackTwo = new Stack<int>();

Однако допустим, что в другой точке кода создается другой класс Stack<T> с другим типом значения, например long, или с определенной пользователем структурой в качестве параметра. В результате среда выполнения генерирует другую версию универсального типа и замещает тип long в соответствующих местах кода MSIL. Дальнейшие преобразования не требуются, потому что каждый специализированный универсальный тип содержит встроенный тип значения.

Действие универсальных типов несколько отличается от ссылочных типов. При первом создании универсального типа с каким-либо ссылочным типом среда выполнения создает специализированный универсальный тип, в котором ссылки на объекты замещены параметрами в коде MSIL. Затем при каждом создании экземпляра построенного типа со ссылочным типом в качестве параметра, (независимо от того, какой это тип) среда выполнения снова использует созданную ранее специализированную версию универсального типа. Это возможно, потому что все ссылки имеют одинаковый размер.

Например, допустим, что существует два ссылочных типа, класс Customer и класс Order, а также допустим, что создан стек типов Customer.

class Customer { }
class Order { }
Stack<Customer> customers;

В этой точке среда выполнения генерирует специализированную версию класса Stack<T>, в котором сохраняются ссылки на объекты, которые будут заполнены позже, а не данные. Допустим, что в следующей строке кода создается стек другого ссылочного типа с именем Order.

Stack<Order> orders = new Stack<Order>();

В отличие о типов значений, другая специализированная версия класса Stack<T> для типа Order не создается. Вместо этого создается экземпляр специализированной версии класса Stack<T>, а также задается переменная orders для ссылки на этот класс. Допустим, что затем встречается строка кода, в которой создается стек типа Customer:

customers = new Stack<Customer>();

Как и в предыдущем случае использования класса Stack<T>, созданного с помощью типа Order, создается новый экземпляр специализированного класса Stack<T>. Содержащиеся в нем указатели ссылаются на область памяти, имеющую размер типа Customer. Так как количество ссылочных типов в разных программах может существенно отличаться, реализация универсальных типов в языке C# значительно сокращает объем кода путем сокращения количества специализированных классов, создаваемых компилятором для универсальных классов ссылочного типа, до одного.

Более того, при создании экземпляра универсального класса в языке C# с помощью типа значения или параметра ссылочного типа, отражение может обращаться к нему с запросами во время выполнения, а также возможно установить его фактический тип и параметр типа.

См. также

Основные понятия

Руководство по программированию в C#

Ссылки

Введение в универсальные шаблоны. (Руководство по программированию на C#)

System.Collections.Generic

Другие ресурсы

Универсальные шаблоны в платформе .NET Framework