Эксперт
Сергей
Сергей
Задать вопрос
Мы готовы помочь Вам.

Цель:

Изучение назначения и структуры системы типов среды CLR.

 

Задачи:

1. Познакомиться со структурой системы типов среды CLR.

2. Провести сравнительный анализ типов-значений и ссылочных типов.

3. Дополнить глоссарий терминов терминологией по данной теме.

Содержание темы:

Система типов среды CLR поддерживает множество языков и стилей программирования, позволяя типам, определенным в одном языке, на равных взаимодействовать с типами других языков.

Система типов (рис.1) логически делится на две подчиненные системы: типы-значения и ссылочные типы.

Рисунок 1 – Система типов в среде CLR

Тип-значение (value type) состоит из последовательности битов в памяти.

Ссылочный тип (reference type) является комбинацией адреса значения (который иногда называется идентификатором (identity) значения) и последовательностью битов значения, т.е. ссылочные типы содержат информацию о расположении и последовательность битов. Расположение обеспечивает идентичность за счет указания области памяти, в которой могут храниться значения.

Поэтому ссылочные типы можно сравнивать по признакам идентичности и равенства.

Идентичность (identity) двух ссылок означает, что они ссылаются на один и тот же объект, а равенство (equality) – что на два разных объекта с одинаковыми данными, т.е. с одинаковой последовательностью битов.

Основное различие между типами заключается в способе доступа к переменным, объявленным с этими типами. Чтобы разобраться в сути этого различия, необходимо кратко пояснить основы динамического использования памяти.

Занимаемая приложением память складывается из двух основных компонентов: стека (stack) и

кучи (heap).

Стек – это область памяти, резервируемая для исполнения программы. Стек напоминает стопку тарелок: если нужна чистая тарелка, берут тарелку из стопки (то есть ту, которую положили последней). С переменными программы происходит то же самое: при вызове функции все объявленные в ней переменные заталкиваются в стек (эта операция называется push); если эта функция вызовет другую функцию, то все переменные, объявленные новой функцией, тоже попадут в стек. Когда функция, вызванная последней, завершится, ее переменные выходят из области видимости (scope) программы и выталкиваются из стека (эта операция называется pop); в результате память, занимаемая этими переменными, освобождается, и выполнение программы продолжается.

Куча – отдельная область памяти, резервируемая для создания объектов, которые предназначены для многократного использования. CLR выделяет в куче память под объекты и управляет утилизацией памяти, занятой неиспользуемыми объектами, посредством механизма под названием сбор мусора.

Память под экземпляры типов значений выделяется из стека. При выходе из области видимости переменной, объявленной с типом значения, переменная уничтожается, а занятая ею память освобождается.

Для переменной ссылочного типа выделяются сразу две области памяти: в куче – под сам объект и в стеке – под переменную с указателем на этот объект. Когда функция обращается к такой переменной, та возвращает адрес объекта, на который она ссылается. Когда же переменная покидает область видимости, уничтожается указатель, но не сам объект. При наличии других ссылок на этот объект он сохраняется, а если все ссылки на объект уничтожены, то он становится добычей сборщика мусора.

На практике ссылочные типы и типы-значения имеют ряд отличий:

  •  типы-значения всегда непосредственно наследуются от типа System.ValueType или System.Enum, которые, в свою очередь, унаследованы от типа System.ValueType. Эти типы всегда закрыты, т.е. никакие другие типы не могут наследоваться от них. Ссылочные типы, наоборот, могут наследоваться от любых классов, кроме System.ValueType или System.Enum.
  •  для ссылочных типов память всегда выделяется в куче, в которой предусмотрена сборка мусора, а для типов-значений память обычно выделяется в стеке. Учтите, что для типов-
  • значений память также может выделяться в куче, в которой предусмотрена сборка мусора, например как для членов ссылочных типов.
  •  доступ к ссылочным типам осуществляется с помощью строго типизированных ссылок (strongly typed references). Эти ссылки обновляются при удалении объекта во время сборки мусора.

Как уже упоминалось, в терминологии CLR экземпляр любого типа (типа-значения или ссылочного типа) называется значением (value).

В качестве примеров типов значений можно привести элементарные типы данных: целочисленные, вещественные, булевы, символьные и т.п., а также определяемые пользователем: структуры и перечислимые типы.

Большинство ссылочных типов представлено классами. Кроме того, к ссылочным типам относятся интерфейсы, делегаты и массивы.

На основе типов-значений нельзя создать иерархию типов, т.е. один тип-значение не может наследовать другой тип-значение. В терминологии среды CLR такой тип называется опечатанным (sealed). На основании типа-значения нельзя создать подчиненный тип.

Ссылочные типы в среде CLR также могут быть объявлены как опечатанные, что позволяет запретить создание подчиненных типов на основании этих типов. Примером опечатанного ссылочного типа в среде CLR является класс String.

Для каждого типа-значения, включая определенные пользователем, существует соответствующий объектный тип, который называется упакованным (boxed) типом. Среда CLR автоматически генерирует упакованные типы для определенных пользователем типов-значений, что предоставляет возможность упаковки и распаковки любых типов-значений.

  • упаковка (boxing) типа-значения – это копирование данных значения в объект упакованного типа, для которого выделяется память в куче, где организована сборка мусора.
  • распаковка (unboxing) типа-значения – это возвращение указателя на фактические данные, т.е. последовательность битов, хранимых в упакованном объекте.

Возможность преобразования всех типов-значений в соответствующие им объектные типы предполагает, что все значения в такой системе типов можно в случае необходимости рассматривать как объекты. Эта ситуация позволяет унифицировать два фундаментально разных типа в среде CLR, потому что любой объект можно рассматривать как подчиненный объект Object. Упакованный тип является объектным типом, поэтому может поддерживать интерфейсные типы, предлагая дополнительные функции для своего распакованного представления.

Во многих языках программирования объектные типы называются классами. Встроенные объектные типы включают Object и String. В среде CLR термин объект (object) используется для значений объектного типа, а все точные типы всех объектов называются объектными типами (object types), String является объектным типом, поэтому все экземпляры типа string являются объектами. Память для объектных типов всегда выделяется в куче со сборкой мусора.

Все объектные типы прямо или косвенно наследуются от типа System.Оbject среды CLR. Основное преимущество класса Object заключается в его способности поддерживать иерархию наследования с единым корнем для всех типов в среде CLR.

Класс Object содержит несколько методов, которые можно вызывать по отношению к объектам:.

  •  метод Equals определяет, равны ли между собой два объекта, и возвращает значение true, если два объекта равны.
  •  метод Finalize вызывается сборщиком мусора перед возвратом памяти, используемой данным объектом. Во время выполнения программы сборка мусора не гарантируется, поэтому данный метод, возможно, даже не будет вызван.
  •  метод GetType возвращает тип данного объекта и предоставляет доступ к метаданным объекта. Статический метод класса Туре может использоваться для той же цели, и для его применения не требуется создавать экземпляр данного класса.
  •  метод MemberwiseClone возвращает частичную копию (shallow copy) объекта. Частичная копия объекта представляет собой новый экземпляр того же типа, который содержит копии всех нестатических полей исходного объекта, т.е. для полей с типам и значениями содержит полные побитовые копии, а для полей со ссылочными типами – копии ссылок, но не сами объекты, на которые они ссылаются. .
  •  метод ReferenceEquals определяет, указывают ли ссылки на один и тот же объект, и возвращает значение true, если обе объектные ссылки, переданные методу, относятся к одному объекту. Он также возвращает значение true, если обе объектные ссылки равны null.
  •  метод ToString возвращает строку, которая представляет этот объект. Согласно определению типа Оbject, для него этот метод возвращает имя типа объекта, т.е. его точный тип.

Аналогично классу Object, класс String является встроенным типом среды CLR. Этот класс является “опечатанным”, т.е. ни один тип не может быть его подчиненным типом. Объекты типа String доступны только для считывания, т.е. вызов любого метода для изменения строки приводит к созданию новой строки.

 

Была ли полезна данная статья?
Да
65.95%
Нет
34.05%
Проголосовало: 185

или напишите нам прямо сейчас:

Написать в WhatsApp Написать в Telegram