Что происходит со стеком при передаче объекта и структуры в функцию в C#
Что проверяют
Понимаете ли вы, что в C# по умолчанию всё передаётся по значению, и что разница между классом и структурой в том, что именно копируется. Формулировка «объекты передаются по ссылке» считается на собеседовании ошибкой, а не оговоркой.
Как отвечать
Разделите три вещи: что копируется, где лежит копия и что видно снаружи.
- Структура копируется целиком. Копия ложится в кадр стека вызываемого метода, и изменения её полей внутри метода оригинала не касаются.
- Класс тоже передаётся по значению, но значением здесь является ссылка. В стек уходит копия ссылки, сам объект остаётся в куче. Поэтому изменение поля через параметр снаружи видно, а присваивание параметру нового объекта нет: перезаписана копия ссылки.
refпередаёт ссылку на саму переменную, и тогда снаружи видно и присваивание.outэто тот же механизм с требованием записать значение,inдаёт доступ только для чтения.
Оговорите, что утверждение «структуры лежат в стеке» верно лишь для локальных переменных. Поле-структура внутри класса лежит в куче вместе с объектом, элемент массива структур тоже, а переменная, захваченная замыканием или асинхронным методом, уезжает в кучу вместе со всем состоянием.
Про производительность: копирование крупной структуры дороже передачи ссылки, поэтому такие структуры делают readonly struct и передают через in.
Где спотыкаются
Заучивают «классы по ссылке, структуры по значению» и тонут на вопросе, что будет, если внутри метода присвоить параметру новый объект. Снаружи не изменится ничего, и объяснить это через «по ссылке» невозможно.
Ставят in на обычную структуру и получают обратный эффект. Компилятор обязан защищать значение от изменения и делает скрытую копию на каждом обращении к методу или свойству, поэтому оптимизация оборачивается замедлением.
Делают изменяемую структуру и ловят исчезающие правки: обращение к ней через свойство, элемент коллекции или интерфейс возвращает копию, и изменение уходит в неё. Именно поэтому изменяемых структур избегают, а вовсе не из-за размера.