Будут ли видны изменения свойств объекта снаружи при передаче по ссылке в C#
Что проверяют
Понимаете ли вы разницу между передачей ссылочного типа по значению и передачей по ссылке через ref. Формулировка вопроса подталкивает к ответу «объекты в C# передаются по ссылке», а это неверно. Следом обычно дают код с присваиванием параметру нового объекта и просят сказать, что выведется.
Как отвечать
По умолчанию в C# все аргументы передаются по значению. Для ссылочного типа (class) значением является сама ссылка: метод получает копию ссылки на тот же объект в куче.
- изменение свойств:
person.Name = "Alice"внутри метода видно снаружи, потому что обе ссылки указывают на один объект. Это работает и безref; - переприсваивание параметра:
person = new Person()внутри метода снаружи не видно. Метод поменял свою копию ссылки, исходная переменная указывает на старый объект; ref: передаётся ссылка на саму переменную, и теперьperson = new Person()меняет переменную вызывающего кода. Переменная должна быть инициализирована,refпишется и при вызове;out: то же, но переменная может быть не инициализирована, а метод обязан присвоить ей значение;in: передача по ссылке только для чтения, полезна для большихstruct, чтобы не копировать их;- структуры: без
refметод получает копию, изменения полей снаружи не видны. Сrefвидны.
Отдельно стоит string: это ссылочный тип, но неизменяемый. Любая «модификация» создаёт новую строку, поэтому снаружи метода изменения не видно, как и при переприсваивании.
Где спотыкаются
Говорят «классы передаются по ссылке» и на примере с person = new Person() внутри метода ошибаются в выводе. Точная формулировка: ссылка передаётся по значению.
Забывают про ловушку изменяемых структур. Свойство, возвращающее struct, отдаёт копию: obj.Position.X = 10 не компилируется (ошибка CS1612), а через локальную переменную молча меняется копия, а не исходное значение.
Путают ref и out или считают, что in запрещает менять свойства объекта. Для ссылочного типа in запрещает только переприсвоить параметр, поля самого объекта менять можно.