Разработка и Конфигурация · 9 мин
Мутабельные значения в 1С: что это и как с ними работать
Мутабельные значения в 1С: что это такое, чем отличаются от иммутабельных, как передаются в процедуры и функции, типичные ошибки и способы избежать побочных эффектов.
Мутабельные значения в 1С — это объекты, содержимое которых можно изменить после создания, не создавая новый объект. К ним относятся массивы, структуры, соответствия, таблицы значений, списки значений и объекты метаданных вроде справочников и документов. Если переменная ссылается на такой объект, любые изменения через эту переменную видны всем, кто держит ту же ссылку.
Противоположность им — иммутабельные (неизменяемые) значения: числа, строки, даты, булево, типы. При «изменении» строки платформа фактически создаёт новую строку, а старая остаётся нетронутой. Поэтому копирование числа в другую переменную безопасно, а копирование массива — нет: обе переменные будут смотреть на один и тот же массив.
Понимание этой разницы критично при передаче параметров в процедуры и функции, при кэшировании данных и при работе с коллекциями в циклах. Большинство трудноуловимых ошибок в коде 1С — «самопроизвольно» меняющиеся таблицы, портящиеся параметры, странные итоги — связаны именно с непониманием мутабельности.
Что такое мутабельность и какие типы 1С к ней относятся
Мутабельность (от англ. mutable — изменяемый) означает, что внутреннее состояние объекта можно менять без создания нового экземпляра. В 1С мутабельными являются практически все коллекции и прикладные объекты: массив, структура, соответствие, таблица значений, дерево значений, список значений, а также объекты типа СправочникОбъект, ДокументОбъект, запись регистра. У массива можно заменить элемент по индексу, у структуры — поменять значение свойства, у таблицы значений — добавить или удалить строку, и все эти операции меняют тот же самый объект в памяти.
Иммутабельные типы — это примитивы: число, строка, дата, булево, неопределено, NULL, тип. Когда вы «дописываете» строку через конкатенацию, платформа создаёт новую строку, а старая остаётся как была. Поэтому присваивание Б = А для примитивов создаёт независимую копию значения, а для коллекций — лишь вторую ссылку на тот же объект.
Как мутабельные значения передаются в процедуры и функции
Главное практическое следствие мутабельности проявляется при передаче параметров. По умолчанию параметры в 1С передаются по ссылке: если процедура получает массив или таблицу значений и меняет их внутри, изменения останутся и в вызывающем коде. Для примитивов это не страшно — число внутри процедуры можно переприсвоить, и снаружи переменная не изменится (если не использовать Знач, поведение для присваивания одинаково), но для коллекций эффект принципиально другой.
Ключевое слово Знач перед параметром заставляет платформа передать копию значения. Для примитивов это почти ничего не меняет, а для мутабельных объектов создаётся копия коллекции — изменения внутри процедуры не затронут оригинал. Однако копия обычно неглубокая: если массив содержит другие массивы, вложенные объекты останутся общими.
Процедура ДобавитьСтроку(Знач Таблица)
НоваяСтрока = Таблица.Добавить();
НоваяСтрока.Сумма = 100;
КонецПроцедуры
// Без Знач таблица вызывающего кода получила бы новую строку.
// С Знач оригинал останется без изменений.Признак того, что параметр меняется намеренно, — отсутствие Знач в объявлении и явный комментарий в коде. Если процедура должна вернуть результат через параметр, это допустимый приём, но его нужно документировать, иначе вызывающий разработчик столкнётся с неожиданным побочным эффектом.
Копирование коллекций: когда присваивание не работает
Типичная ошибка новичка — попытаться «скопировать» таблицу значений присваиванием: Таблица2 = Таблица1. В результате обе переменные указывают на одну таблицу, и очистка одной очищает обе. Для реального копирования у коллекций есть специальные методы: у таблицы значений — Скопировать(), у массива копию можно получить перебором или через сериализацию, у структуры — вставкой в новую структуру.
Метод Скопировать() у таблицы значений создаёт независимую копию со всеми строками и колонками. У него есть варианты с отбором строк и списком колонок, что удобно, когда нужна только часть данных. Для структур глубокого копирования «из коробки» нет: вложенные структуры и массивы придётся копировать рекурсивно вручную.
Мутабельные объекты в кэше и повторном использовании
Мутабельность особенно опасна при кэшировании. Если вы помещаете структуру с настройками или таблицу значений в кэш (в переменную модуля, в параметры сеанса, в фоновое хранилище), а потом где-то меняете полученный из кэша объект, вы меняете и сам кэш. Следующий потребитель получит уже изменённые данные, и найти источник порчи бывает очень трудно.
Безопасный шаблон — возвращать из кэша копию: Скопировать() для таблиц, новую структуру для структур. Альтернатива — хранить в кэше сериализованное значение (например, через ЗначениеВСтрокуВнутр) и восстанавливать его при каждом обращении, что гарантирует свежий объект, но стоит дороже по производительности.
Мутабельность прикладных объектов: справочники и документы
Объекты данных вроде СправочникОбъект и ДокументОбъект — тоже мутабельные, но с важным отличием: изменения живут только в памяти, пока не вызван метод Записать(). До записи можно свободно менять реквизиты и табличные части, отменить всё простым прекращением работы с объектом. После записи изменения фиксируются в базе, и откат возможен только в рамках транзакции.
Здесь частая ошибка — получение объекта через ПолучитьОбъект() по ссылке «просто посмотреть». Объектная модель мутабельна и тяжеловесна: для чтения данных почти всегда правильнее использовать запрос или обращение к реквизитам через ссылку. Получение объекта оправдано только когда планируется изменение и запись.
Сравнение вариантов
Подходит, когда нужно изменить и записать данные. Тяжёлая операция, требует блокировки, изменения фиксируются только после Записать()
Подходит для чтения: быстро, без блокировок, результат — новая независимая выборка. Не позволяет записывать
Подходит для точечного изменения одной записи регистра сведений без чтения всего набора
Как проверить код на проблемы с мутабельностью
Признак проблемы — данные «меняются сами»: таблица после вызова процедуры содержит лишние строки, настройки из кэша отличаются от заданных, итоги расходятся при повторном расчёте. Чтобы локализовать, проверьте три вещи: передаётся ли коллекция без Знач в места, где она меняется; используется ли присваивание вместо Скопировать(); возвращает ли кэш сам объект вместо копии.
Полезная практика — договориться в команде о соглашении: параметры, которые процедура намеренно меняет, помечаются в имени или комментарии, а всё остальное объявляется с Знач. Это делает побочные эффекты видимыми уже при чтении сигнатуры.
Как проверить результат
Объявлен с Знач, если менять оригинал не нужно
Без Знач, и внутри есть Добавить/Очистить/Удалить
Используется метод Скопировать()
Простое присваивание переменных
Возвращается копия объекта
Возвращается сам кэшированный объект, который потом меняют
Практические рекомендации
Работая с мутабельными значениями, придерживайтесь простых правил: считайте любую коллекцию общей, пока не доказано обратное; копируйте данные на границах модулей и при возврате из кэша; используйте Знач для параметров, которые функция не должна менять; для чтения прикладных данных предпочитайте запросы получению объектов.
Что важно запомнить
Мутабельные значения в 1С — коллекции и объекты данных, изменяемые по ссылке. Они передаются в процедуры по ссылке, копируются только специальными методами, а их изменение в одном месте видно везде. Контролируйте копирование и используйте Знач — это устраняет большинство побочных эффектов.
Частые вопросы
Чем мутабельные значения отличаются от иммутабельных в 1С?
Мутабельные (массив, структура, таблица значений, объекты данных) можно менять по ссылке после создания. Иммутабельные (число, строка, дата, булево) при любом «изменении» порождают новое значение, поэтому их копирование присваиванием безопасно.
Почему после вызова процедуры моя таблица значений изменилась?
Потому что таблица передана по ссылке, а внутри процедуры её изменили. Чтобы защитить оригинал, объявите параметр с ключевым словом Знач или передайте копию через Скопировать().
Как правильно скопировать массив в 1С?
Простое присваивание копирует только ссылку. Для независимой копии создайте новый массив и перенесите элементы циклом, либо сериализуйте и восстановите значение. Учтите, что вложенные коллекции при этом тоже нужно копировать отдельно.
Делает ли Знач глубокую копию структуры?
Нет. Знач создаёт копию верхнего уровня: вложенные массивы и структуры внутри остаются общими с оригиналом и могут быть изменены через оба экземпляра.
Опасно ли менять объект, полученный из кэша?
Да, если кэш возвращает сам объект, а не копию. Изменение испортит кэшированные данные для всех последующих обращений. Правильный шаблон — возвращать из кэша копию коллекции.
Когда изменения мутабельного объекта документа попадают в базу?
Только после вызова метода Записать(). До записи все изменения существуют лишь в памяти; после записи они фиксируются в базе в рамках транзакции.