Common Type System

Эта статья находится на начальном уровне проработки, в одной из её версий выборочно используется текст из источника, распространяемого под свободной лицензией
Материал из энциклопедии Руниверсалис

Common Type System (сокр. CTS, рус. Общая система типов) — часть .NET Framework, формальная спецификация, определяющая, как какой-либо тип (класс, интерфейс, структура, встроенный тип данных) должен быть определён для его правильного выполнения средой .NET. Кроме того, данный стандарт определяет, как определения типов и специальные значения типов представлены в компьютерной памяти. Целью разработки CTS было обеспечение возможности программам, написанным на различных языках программирования, легко обмениваться информацией. Как это принято в языках программирования, тип может быть описан как определение набора допустимых значений (например, «все целые от 0 до 10») и допустимых операций над этими значениями (например, сложение и вычитание).

Спецификация для CTS закреплена в стандарте Ecma 335, озаглавленном «Common Language Infrastructure (CLI) Partitions I to VI» (рус. Общеязыковая инфраструктура, главы с I по IV). CLI и CTS были разработаны корпорацией Microsoft, а Microsoft .NET framework — реализация стандарта.

Функции Common Type System

  • Формирует фреймворк, способствующий межъязыковой интеграции, безопасности типов, а также высокой производительности исполнения кода.
  • Обеспечивает объектно-ориентированную модель, поддерживающую полную реализацию множества языков программирования.
  • Определяет правила, которым должны следовать языки, что в том числе позволяет гарантировать, что объекты, написанные на разных языках могут друг с другом взаимодействовать.
  • CTS определяет правила, гарантирующие, что типы данных объектов, написанные на разных языках, смогут взаимодействовать друг с другом.
  • CTS определяет правила для видимости типов и доступа к членам типа, то есть CTS утверждает правила, по которым сборки формируют области видимости для типа, а Common Language Runtime дополняет правила видимости.
  • CTS определяет правила, управляющие наследованием типов, виртуальными методами и продолжительностью существования объектов.
  • Языки, поддерживаемые платформой .NET, могут реализовывать все или некоторые из общих типов данных.

При округлении дробных значений благодаря фреймворку по умолчанию применяется метод банковского округления. Начиная с версии 2, «симметричное арифметическое округление» («англ. Symmetric Arithmetic Rounding») (округляет до ближайшего числа со стороны нуля) также доступно программистам в качестве дополнительной возможности[1].

Категории типов

Стандартная система типов поддерживает две основные категории типов:

Значимые типы
Переменные значимых типов непосредственно содержат данные, а экземпляры значимых типов располагаются или в стеке или непосредственно в теле других объектов. Значимые типы могут быть встроенными (реализуются средой исполнения), пользовательскими или перечислениями. Значение значимого типа может быть преобразовано в значение ссылочного типа путём применения к нему процедуры упаковки (боксинга, boxing).
Ссылочные типы
Переменные ссылочных типов хранят лишь ссылку на адрес в памяти, по которому хранится значение (объект). Экземпляры ссылочных типов располагаются в куче (за исключением случая когда речь идет о указателях). Ссылочные типы делятся на самоописывающиеся типы, указатели и интерфейсы. Тип ссылочного типа может быть определен по значению самоописывающего типа. Самоописывающие типы делятся на массивы и классы. Классы в свою очередь делятся на пользовательские классы, упаковочные (boxed) значимые типы и делегаты.

Нижеследующий пример, написанный на языке Visual Basic .NET, демонстрирует различие между ссылочными типами и значимыми типами:

Imports System

Class Class1
    Public Value As Integer = 0
End Class 'Class1
 
Class Test
    Shared Sub Main()
        Dim val1 As Integer = 0
        Dim val2 As Integer = val1
        val2 = 123
        Dim ref1 As New Class1()
        Dim ref2 As Class1 = ref1
        ref2.Value = 123
        Console.WriteLine("Значения: {0}, {1}", val1, val2)
        Console.WriteLine("Ссылки: {0}, {1}", ref1.Value, ref2.Value)
    End Sub 'Main
End Class 'Test

Вышеприведенный пример выводит следующее:

Значения: 0, 123
Ссылки: 123, 123

Упаковка и распаковка

Упаковка

Значение значимого типа может быть преобразовано в значение ссылочного типа путём применения к нему процедуры упаковки (боксинга, англ. boxing). При этом значение переносится в кучу, и возвращается управляемая ссылка на область кучи содержащую это значение. Как видно из примера приведенного ниже, в C# нет необходимости указывать компилятору, что необходимо упаковать Int32-значение, превратив его тем самым в объект, поскольку компилятор C# сам выявляет такую необходимость и вставляет соответствующий код (IL). Однако это не относится к возможностям среды выполнения, а является поведением компилятора. Так в языке F# упаковка производится только если программист явно указал её необходимость.

Int32 x = 10; 
object o = x ; // Неявная упаковка
Console.WriteLine("Объект o = {0}",o); // печатает 10

Однако, Int32 всегда может быть упакован явным образом, как показано ниже:

Int32 x = 10; 
object o = (object) x; // Явная упаковка
Console.WriteLine("Объект o = {0}",o); // печатает 10

Распаковка

Процесс, обратный упаковке называется распаковкой (англ. unboxing). Нижеследующий пример демонстрирует как в языке C# распаковать запакованный до этого значимый тип.

Int32 x = 5; 
object o1 = x; // Неявная упаковка
x = (int)o1; // Явная распаковка

Необходимо отметить, что в данном пример распаковка требует явного приведения типов. Это связано с тем, что запакованное значение имеет тип object, а распаковка требует указания конкретного типа. Начиная с C# 4.0 вместо типа object можно использовать тип dynamic, что позволяет обходиться без явного приведения типов.

dynamic x = 42;
int y = x; // Неявная распаковка

См. также

Примечания

Ссылки