Типы значений и ссылочные типы

Последнее обновление: 30.10.2015

Итак, в прошлых темах мы рассмотрели различные типы данных - как примитивные типы Integer, Double и др., так и комплексные типы - классы и структуры. Все типы данных в Visual Basic.NET можно разделить на две группы: типы значений или значимые типы (value types) и ссылочные типы (reference types). И при создании программ очень важно понимать между ними различия для корректной работы приложения.

Типы значений представлены следующими типами данных:

  • Целочисленные типы (Byte, SByte, Char, Short, UShort, Integer, UInteger, Long, ULong)

  • Типы с плавающей запятой (Single, Double)

  • Тип Decimal

  • Тип Boolean

  • Перечисления Enum

  • Структуры

Ссылочные типы:

  • Тип Object

  • Тип String

  • Классы

  • Интерфейсы

  • Делегаты

Различия между этими типами данных основываются на разном подходе к организации их в памяти. Вся память в .NET делится на два типа: стек и куча (heap). Типы значений являются производными от типа System.ValueType и размещают свое значение в стеке. Стек представляет собой структуру данных, которая растет снизу вверх: каждый новый добавляемый элемент помещаются поверх предыдущего. Время жизни переменных таких типов ограничено их контекстом. Физически стек - это некоторая область памяти в адресном пространстве.

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

Например:

Sub SomeMethod (t As Integer)
    Dim x As Integer = 5
    Dim y As Integer = 6
    Dim z As Integer = x * y * t
End Sub

При вызове этого метода в стек будут помещаться переменные t, x, y и z. Все эти переменные определены в контексте метода SomeMethod. Вне его они не существуют. И после завершения работы метода они уничтожаются, а память очищается.

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

При создании объекта ссылочного типа в стеке помещается ссылка на адрес в куче (хипе). Когда объект ссылочного типа перестает использоваться, то ссылка из стека удаляется. После этого в дело вступает автоматический сборщик мусора (garbage collector): он видит, что на объект в хипе нету больше ссылок, и удаляет этот объект и очищает память.

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

Sub Test()
    Dim state1 As State = New State() 'State - структура, ее данные размещены в стеке
    Dim country1 As Country = New Country() 'Country - класс, в стек помещается ссылка на адрес в хипе
											'а в хипе располагаются все данные объекта country1
End Sub

Class Country
    Public x As Integer
    Public y As Integer
End Class

Structure State
    Public x As Integer
    Public y As Integer
End Structure

Метод Test создает два объекта - структуру и объект класса. Программа выделяет в стеке память для объекта state1. Также в стеке создается ссылка для объекта country1 (Country country1), а с помощью конструктора выделяется место в хипе (new Country()).

В итоге в стеке будут храниться все поля структуры state1 и адрес на все поля объекта country1 в хипе.

Копирование значений

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

Sub Test()
    Dim state1 As New State()
    Dim state2 As New State()
    state2.x = 1
    state2.y = 2
    state1 = state2
    state2.x = 5  'state1.x=1 по-прежнему

    Dim country1 As New Country()
    Dim country2 As New Country()
    country2.x = 1
    country2.y = 4
    country1 = country2
    country2.x = 7 ' теперь и country1.x = 7, так как обе ссылки и country1 и country2 
    'указывают на один объект в хипе
End Sub

Так как state1 - структура, то при присвоении state1 = state2 она получает копию структуры state2. А объект класса country1 при присвоении country1 = country2; получает адрес ссылки на тот же объект, на который указывает country2. Поэтому с изменением country2, так же будет меняться и country1.

Ссылочные типы внутри типов значений

Рассмотрим более сложный пример, когда внутри структуры может храниться объект ссылочного типа, например, какого-нибудь класса:

Sub Test()
    Dim state1 As New State()
    Dim state2 As New State()
    state2.country = New Country()
    state2.x = 2
    state2.country.x = 5
    state1 = state2
    state2.country.x = 8 ' теперь и state1.country.x=8, так как state1.country и state2.country
    ' указывают на один объект в хипе
End Sub

Class Country
    Public x As Integer
    Public y As Integer
End Class

Structure State
    Public x As Integer
    Public y As Integer
    Public country As Country
End Structure

Объекты ссылочных типов данных, хранящиеся в структурах, также размещают в стеке адрес ссылки на объект в хипе. Поэтому при присвоении двух структур state1 = state2; структура state1 также получит ссылку на объект country в хипе. Поэтому изменение state2.country повлечет за собой также изменение state1.country.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850