Здесь присутствуют две дихотомические проблемы со схожим словарным запасом: значение в сравнении со ссылкой типы и передача переменных по значению по сравнению со ссылкой.
Значение v. СсылкаТипы
Первая проблема - значение по сравнению с эталонной типами .Типы значений передаются путем копирования - обычно.Типы значений:
- Дата
- Char
- U / Int (16/32/64)
- Десятичное число
- Single и Double
- Boolean
- Структуры
- Перечисления
Все, кроме перечисленных выше типов, являются ссылочными типами.Когда объект передается вокруг, на самом деле передается адрес его памяти, который часто рассматривается как int на 32-битных платформах и long на 64-битных платформах.
Передача по значению vПо ссылке
Вторая проблема заключается в передаче переменной по значению в сравнении со ссылкой.
Переменная - это слот в определенной позиции в памяти, который может содержать вещи.Для типов значений это содержит фактическое значение.Для ссылочных типов он содержит адрес памяти объекта в куче (или равен Nothing).
По значению
Когда вы передаете переменную по значению, что угоднонаходится в ячейке памяти этой переменной, это то, что копируется.Для типов значений это означает, что само значение копируется.Для ссылочных типов то, что копируется, является адресом памяти объекта, на который ссылается переменная.
По ссылке
Помните, что переменная - это просто слот в памятидля хранения вещей.Когда вы передаете переменную по ссылке, вы передаете адрес этого слота (в отличие от данных в этом слоте).
Если эта переменная является типом значения, в этом слоте хранится само значение, поэтому передаваемая вещь является указателем на значение.
Если эта переменная является ссылочным типом, слот содержит указатель на местоположение объекта в памяти, поэтому передаваемая вещь - это указатель на вашу переменную (как с типами значений), которая сама содержит другойуказатель (не похожий на типы значений), который ведет к ячейке памяти, в которой содержится объект, на который ссылается переменная.
Это позволяет функции изменять переменную в другой функции, например:
Sub IPassByReference
Dim myVariable As Boolean = False
IReceiveByReference myVariable
Debug.Print(myVariable.ToString()) 'Always prints True
End Function
Sub IReceiveByReference(ByRef flag As Boolean)
flag = True 'the memory address of myVariable was passed.
End Function
Давайте сравним с ситуацией, когда вы передаете по значению:
Sub IPassByValue
Dim myVariable As Boolean = False
IReceiveByValue myVariable
Debug.Print(myVariable.ToString()) 'Always prints False
End Function
Sub IReceiveByValue(ByVal flag As Boolean)
flag = True 'the value of myVariable was passed.
End Function
В приведенном выше примере Boolean является типом значения.Если бы это был объект, IReceiveByReference мог бы указать myVariable на совершенно новый объект, потому что он получил адрес myVariable, а не адрес объекта, на который указывает myVariable.Напротив, IReceiveByValue было передано только содержимое myVariable, поэтому он не может изменить myVariable, чтобы он указывал на новый объект.Тем не менее, он может изменить объект, задав его поля и свойства и вызвав методы.
Return By-Reference?
Хотя функции могут передавать переменные по ссылке,они не могут вернуть их таким образом.Когда функция возвращается, ее локальные переменные больше не существуют (или ожидают очистки, если они выделены в куче).Поэтому функции всегда возвращаются по значению;поскольку локальные переменные больше не имеют действительных адресов памяти, нет никаких ссылок на переменные, которые возвращают .
Собирая все это вместе, когда вы возвращаете объект из функции,единственное, что копируется, это адрес объекта.Когда вы возвращаете тип значения из функции, само значение копируется.
Это означает, что ссылочные типы являются по существу типами значений, где значение является адресом памяти объекта в куче (или Nothing).