Значение по умолчанию byValue для ВСЕХ типов, но важно понимать, что означают эти две опции для «ссылочного типа» (класса), а не для типа значения. (структуры).
Для ссылочного типа, если вы объявляете переменную ссылочного типа в методе, эта переменная является ячейкой памяти в стековом кадре метода. Это не в куче. Когда вы инициализируете эту переменную (используя new или factory, что угодно), вы создали реальный объект в куче, и адрес этого объекта сохраняется в объявленной ссылочной переменной в фрейме стека ваших методов.
Когда вы передаете ссылочный тип другому методу byVal, вы создаете копию адреса, хранящегося в стеке вызывающих методов, и передаете копию этого значения (адрес указателя) в вызываемый метод, где он сохраняется в новый слот памяти в стеке вызываемых методов. Внутри вызываемого метода новая клонированная переменная указывает непосредственно на тот же объект в куче. Таким образом, используя его можно изменить свойства одного и того же объекта. Но вы не можете изменить, на какой объект кучи указывает исходная ссылочная переменная (в стеке вызывающих методов).
Если в вызываемом методе я пишу
myVar = new object();
Исходная переменная в вызывающем методе не будет изменена, чтобы указывать на новый объект.
Если я передаю ссылочный тип byRef, otoh, я передаю указатель на объявленную переменную в стеке вызывающих методов (который содержит указатель на объект в куче). Следовательно, это указатель на указатель на объект. , Он указывает на область памяти в стеке вызывающих методов, которая указывает на объект в куче.
Так что теперь, если я изменяю значение переменной в вызываемом методе, устанавливая его в новый объект (), как указано выше, поскольку это «ссылка на переменную в вызывающем методе», я фактически изменяю, какой объект переменная в вызывающем методе указывает на. Поэтому после возврата вызванного метода переменная в вызывающем методе больше не будет указывать на тот же исходный объект в куче.