Время авторизации:
(1) Создаем метод вызова Main()
(2) он создает объект List (который является объектом ссылочного типа) и сохраняет его в переменной myList
.
public sealed class Program
{
public static Main()
{
List<int> myList = new List<int>();
Во время выполнения:
(3) Среда выполнения выделяет память в стеке в # 00, достаточно широкую для хранения адреса (# 00 = myList
, поскольку имена переменных на самом деле являются просто псевдонимами для областей памяти)
(4) Runtime создает список объектов в куче в ячейке памяти #FF (все эти адреса, например, sakes)
(5) Затем среда выполнения сохранит начальный адрес #FF объекта в # 00 (или в словах, сохранит ссылку на объект List в указателе myList
)
Назад ко времени авторизации:
(6) Затем мы передаем объект List в качестве аргумента myParamList
вызываемому методу modifyMyList
и назначаем ему новый объект List
List<int> myList = new List<int>();
List<int> newList = ModifyMyList(myList)
public List<int> ModifyMyList(List<int> myParamList){
myParamList = new List<int>();
return myParamList;
}
Во время выполнения:
(7) Runtime запускает подпрограмму вызова для вызываемого метода и как ее часть проверяет тип параметров.
(8) При нахождении ссылочного типа он выделяет память в стеке на # 04 для наложения псевдонима переменной параметра myParamList
.
(9) Затем в нем также сохраняется значение #FF.
(10) Runtime создает объект списка в куче в ячейке памяти # 004 и заменяет #FF в # 04 этим значением (или разыменовывает исходный объект List и указывает на новый объект List в этом методе)
Адрес в # 00 не изменяется и сохраняет ссылку на #FF (или оригинальный указатель myList
не нарушается).
Ключевое слово ref - это директива компилятора, пропускающая генерацию кода времени выполнения для (8) и (9), что означает, что для параметров метода не будет выделяться куча. Он будет использовать оригинальный указатель # 00 для работы с объектом в #FF. Если исходный указатель не инициализирован, среда выполнения остановится, что приведет к невозможности продолжения работы, поскольку переменная не инициализирована
Ключевое слово out - это директива компилятора, которая почти такая же, как ref с небольшими изменениями в (9) и (10). Компилятор ожидает, что аргумент не будет инициализирован, и продолжит с (8), (4) и (5), чтобы создать объект в куче и сохранить его начальный адрес в переменной аргумента. Неинициализированная ошибка не будет выдана, а все предыдущие сохраненные ссылки будут потеряны.