Общая система типов (CTS - Common Type System?)
Общая спецификация типов означает, что промежуточный язык содержит богатый набор предопределенных типов данных. Они организованы в иерархию типов, характерную для сред объектно-ориентированного программирования.
Итак, набор предопределенных типов данных организован в некоторую иерархию типов
Важность для совместимости языков
Причина, по которой важна общая спецификация типов, заключается в том, что если класс наследуется от другого класса или содержит экземпляры других классов, то он должен знать, какие типы данных используются в других классах.
Именно отсутствие в прошлом какой-либо общей системы для определения этой информации и являлось тем барьером, который не позволял осуществлять наследование между языками. Такой тип информации не представлялся в стандартном исполняемом файле или DLL.
В некотором смысле проблема получения доступа к информации о типах решается посредством метаданных в сборках. Предположим, что пишется класс на С# и он должен быть унаследован от класса, написанного на VB.NET. Для этого необходимо указать компилятору, в какой сборке определен этот класс VB.NET. Компилятор может использовать метаданные из этой сборки для выяснения того, какие методы, свойства, поля и т.п. содержит класс VB.NET. Очевидно, что компилятору необходима эта информация для компиляции исходного кода. Для разработчиков на C++ это является аналогом включения заголовочного файла. Одной из целей заголовочных файлов в C++ можно считать предоставление информации о доступных типах исходным файлам.
Однако компилятору требуется больше информации, нежели могут предоставить метаданные. Предположим, что один из методов класса VB.NET возвращает тип integer- один из стандартных типов VB.NET. С# не имеет типа данных с таким именем. Очевидно, что создавать производный класс, использовать этот метод и возвращаемое им значение можно только в том случае, если компилятор знает, как привести значение типа Integer VB.NET к некоторому известному типу, определенному в С#.
Это возможно, поскольку общая спецификация типов описывает предопределенные типы данных, доступные в промежуточном языке, так что все языки, предназначенные для -NET, будут генерировать код, основанный на этом наборе типов. В нашем примере тип integer VB на самом деле представляет собой 32- разрядное целое со знаком, которому соответствует тип int32 промежуточного языка. Таким образом, в промежуточном коде переменная будет иметь именно этот тип данных. Так как компилятор С# осведомлен об этом типе, проблемы не возникает. На уровне исходного кода язык С# обращается к Int32 с помощью ключевого слова int. и компилятор будет трактовать метод VB.NET как возвращающий значение типа int.
Иерархия CTS
Общая система типов не только специфицирует простые типы данных, но и описывает обширную иерархию типов с четким определением позиций, в которых код имеет право определять свои собственные типы. Иерархическая структура общей системы типов отражает объектную методологию промежуточного языка и выглядит примерно следующим образом:
В этом дереве типы представляют собой:
Тип | Значение |
Массивы | Любой тип, который содержит массив объектов. |
Упакованные типы по значению | Тип по значению, который временно приведен к типу по ссылке гак, что он может храниться в куче. |
Встроенные типы по значению | Большинство стандартных базовых типов, которые представляют собой числа, значения Boolean или символы. |
Типы с классами | Типы, описывающие сами себя, но не являющиеся массивами. |
Делегаты | Типы, разработанные для хранения ссылок на методы. |
Перечисления | Наборы перечисляемых значений, в которых каждое значение представляется меткой, но хранится как числовой тип. Например, если необходимо представить таким образом цвета, то перечисления позволят записать {Red, Green, Yellow} вместо {0, 1, 2} |
Интерфейсные типы | Интерфейсы |
Типы-указатели | Указатели |
Тип по ссылке | Любые типы данных, доступ к которым осуществляется по ссылке и которые хранятся в куче |
Самоописываемые типы | Типы данных, которые предоставляют информацию о себе для использования сборщиком мусора |
Тип | Базовый класс, который представляет любой тип |
Определенные пользователем типы по значению | Типы, которые определены в исходном коде и хранятся как типы по значению. В терминах С# это означает любую структуру |
Определенные пользователем типы по ссылке | Типы, которые определены в исходном коде и хранятся как типы по ссылке. В терминах С# это означает любой класс |
Тип по значению | Базовый класс, который представляет собой любой тип по значению |
В этой таблице не приведен список встроенных типов по значению.
В С# каждый предопределенный тип преобразуется компилятором только в один из встроенных типов IL. То же самое справедливо для VB.
Единственный пункт, который требует пояснения, это приведенные типы по значению. Существует ряд обстоятельств, при которых типы по значению необходимо временно преобразовывать в типы по ссылке и сохранять в куче (сюда относятся случаи, когда типы по значению передаются по ссылке в метод и когда они специально согласуются с объектом). Этот процесс известен как упаковка и требует, чтобы для каждого типа по значению существовал соответствующий тип по ссылке, который представлял бы собой упакованную версию этого типа в куче.
Другими словами, всякий раз, когда в коде С# создается тип по значению, .NET формирует для него соответствующий упаковочный тип, который применяется для представления переменных этого типа, если их необходимо использовать как типы по ссылке.