
Глава 2. Типы в языке c#
2.1. Типы ссылок и типы значений
В стандарте C# в связи с типами используется выражение «унифицированная система типов». Смысл унификации состоит в том, что все типы происходят от класса object, то есть являются производными от этого класса и наследуют его свойства. О механизме наследования речь пойдет позднее, но в примерах программ мы будем применять для объектов и классов возможности, унаследованные ими от класса object.
Типы C# позволяют представлять, во-первых, те данные, которые используются в расчетах (целые и вещественные числа, логические значения) и в обработке текстов (символы, строки). Вторая группа типов соответствует специфическим для программирования на языках высокого уровня конструкциям – массивам, структурам, объектам (классам).
Такое деление типов на две названные группы унаследовано языком C# из предшествующих ему языков программирования.
Примечание. В C# имеются типы указателей и тип void, означающий отсутствие значения. Указатели используются только в небезопасных участках кода программ и пока рассматриваться не будут.
Однако при разработке C# решили, что в системе типов целесообразно иметь ещё одно разделение. Поэтому язык C# поддерживает два вида (две категории) типов: типы значений (value types) и типы ссылок (reference types).
Принципиальное различие этих двух видов типов заключается в том, что объект ссылочного типа может именоваться одновременно несколькими ссылками, что абсолютно недопустимо для объектов с типами значений.
Для переменных традиционных языков, например C, всегда соблюдается однозначное соответствие:
имя_переменной => значение_переменной
Точно такая же схема отношений справедлива в языке C# объектов с типами значений:
имя_объекта => значение_объекта
Если рассматривать реализацию такого отношения в программе, то нужно вспомнить, что память компьютера организована в виде последовательности ячеек. Каждая ячейка имеет индивидуальный, обычно числовой адрес (наименьшая из адресуемых ячеек – байт).
При выполнении программы каждому объекту выделяется блок (участок) памяти в виде одного или нескольких смежных байтов. Адрес первого из них считается адресом объекта. Код, находящийся в выделенном для объекта блоке памяти, представляет значение объекта.
Представить машинную реализацию объекта с типом значений можно так:
адрес_объекта => код_значения_объекта
Переменные, имеющие типы значений, непосредственно представляют в программе конкретные данные.
Переменные, имеющие типы ссылок, представляют в программе конкретные данные косвенно, хотя косвенность этого представления не показана явно в тексте программы. Доступ к данным по имени переменной с типом ссылки иллюстрирует триада:
имя_переменной => значение_адреса_данных => значение_данных
Машинную реализацию такой триады можно изобразить так:
адрес_переменной => код_адреса_данных => код_значении_данных
Однако при программировании доступ к данным с помощью ссылки можно воспринимать в соответствии со схемой доступа к данным с помощью традиционной переменной (имеющей тип значений):
имя_ссылки => значение_данных
Но при использовании такой схемы появляется новое и принципиальное отличие - доступность одних и тех же данных (одного участка памяти) с помощью нескольких ссылок:
имя_ссылки_1 \
значение_данных
имя_ссылки_2 /
Основное и принципиальное для программиста-пользователя отличие типов значений от типов ссылок состоит в следующем. Каждой переменной, которая имеет тип значений, принадлежит её собственная копия данных, и поэтому операции с одной переменной не влияют на значения других переменных. Несколько переменных с типом ссылок могут быть одновременно соотнесены с одним и тем же объектом. Поэтому операции, выполняемые с одной из этих переменных, могут изменять объект, на который в этот момент ссылаются другие переменные (с типом ссылок). Различия между типами значений и типами ссылок иллюстрирует ещё одна особенность. Объект ссылочного типа никогда не имеет своего собственного имени.
Если обратить внимание на принципы организации памяти компьютера, то следует отметить, что на логическом уровне она разделена на две части: стек и управляемую кучу (manager heap).
Объекты типов значений как таковые всегда при реализации получают память в стеке. При присваиваниях их значения копируются. Объекты ссылочных типов размещаются в куче.
Как и объекты, переменные могут быть ссылочных типов (ссылки) и типов значений. Переменные с типами значений размещаются в стеке, но являются ссылками на объекты, размещённые в куче.
Следуя [7], можно сказать, что типы значений - это те, переменные которых непосредственно хранят свои данные, тогда как ссылочные типы – это те, переменные которых хранят ссылки, по которым соответствующие данные могут быть доступны. Для краткости термином «переменная» будем называть переменную с типом значения, а ссылкой - переменную со значением ссылочного типа.
Примеры и особенности ссылок рассмотрим чуть позже.