В КУРСЕ?

Разбираемся в теме

C#: значение, ссылка и последствия присваивания

Одна из важных основ C# — различие между типами значений и ссылочными типами. Оно помогает объяснить, почему изменение одной переменной иногда не затрагивает другую, а иногда обе ведут к изменённому объекту. Полезнее начинать с поведения присваивания, чем с лозунга про стек и кучу. Этот разбор касается обычных присваиваний без специальных параметров передачи по ссылке.

Копия значения и копия ссылки дают разные связи

При присваивании значения типа int новая переменная получает собственное значение. Если A равно пяти и B присвоено значение A, последующее изменение B не меняет A. Для ссылочного типа копируется ссылка на объект. Поэтому две переменные могут указывать на один и тот же экземпляр. Представьте список: A ссылается на него, затем B получает ту же ссылку. Добавление элемента через B изменяет общий список, и это видно через A. Но присваивание переменной B ссылки на другой список не перенаправляет A. Различайте изменение объекта и изменение того, на какой объект указывает конкретная переменная.

Тип значения может содержать ссылочные поля

Структура является типом значения, однако её поля могут иметь ссылочные типы. При копировании такой структуры значения полей копируются, а для ссылочного поля это означает копирование ссылки. Поэтому две копии структуры способны продолжать обращаться к одному вложенному объекту. Это показывает, почему выражение копия всегда полностью независима слишком широко. Нужно рассматривать состав данных и глубину копирования. Аналогично ссылочный тип не обязан быть изменяемым: строки в C# являются ссылочными, но неизменяемыми. Операция, выглядящая как изменение строки, создаёт или использует другое строковое значение, а не редактирует символы исходного экземпляра на месте.

Проверяйте поведение маленьким примером

Когда результат кажется неожиданным, нарисуйте переменные отдельно от объектов и проведите стрелки ссылок. Затем выполните каждое действие по порядку. Такой способ позволяет увидеть, где произошло копирование значения, где появилась общая ссылка и где переменная получила новую связь. Не делайте вывод о семантике только из предполагаемого расположения в памяти. Детали размещения зависят от контекста и реализации, а основная модель языка описывает значения и ссылки. Также отдельно изучаются ref, out и другие механизмы, которые меняют правила передачи. Для начального понимания лучше сначала уверенно разбирать обычные случаи без смешения нескольких новых понятий.

Попробуйте на практике

Смоделируйте три коротких сценария C# на бумаге. Компилятор и установка среды не требуются.

  1. Нарисуйте A со значением int 5 и B, получившую значение A. Измените B на 8 и запишите итоговые значения обеих переменных.
  2. Нарисуйте один список с элементом 5 и две ссылки A и B на него. Добавьте через B элемент 8 и покажите, что доступно через A.
  3. Перенаправьте B на новый пустой список. Объясните, почему прежний список по-прежнему доступен через A.
  4. Нарисуйте две копии структуры, в каждой из которых есть поле-ссылка на один общий список. Отметьте, какая часть скопирована и какая остаётся общей.

Как проверить результат. В первом сценарии A остаётся равной 5. Во втором обе ссылки показывают список из двух элементов, в третьем A не меняет объект. В четвёртом копии структуры разделяют вложенный список.

Частые вопросы

Ссылочный тип всегда означает изменяемый объект?

Нет. Например, строки являются ссылочными, но неизменяемыми. Категория типа и возможность изменения содержимого — разные свойства.

Копирование структуры всегда создаёт полную глубокую копию?

Нет. Ссылочные поля копируются как ссылки и могут продолжать указывать на общие объекты. Нужно учитывать состав структуры.

Самостоятельный разбор темы. Содержание конкретной обучающей программы здесь не представлено.

Зарегистрируйтесь, чтобы уточнить возможность доступа к этому материалу

Зарегистрироваться
← К списку материалов