К статье
Практический материал

Разработка и Конфигурация · 12 мин

Мутабельные значения в 1С: что это и как с ними работать

Разбираем, что такое мутабельные и иммутабельные значения в 1С: какие типы изменяемы, где возникают ошибки со ссылками и как защитить данные в коде.

Мутабельность — это свойство значения изменяться «на месте», без создания новой копии. В 1С:Предприятии большинство объектов встроенного языка мутабельны: массив, структура, соответствие, таблица значений, список значений. Когда вы присваиваете такое значение другой переменной или передаёте в процедуру, копируется не содержимое, а ссылка на тот же объект в памяти. Изменение через одну переменную мгновенно видно через все остальные.

Это поведение часто становится источником трудноуловимых ошибок у начинающих разработчиков 1С. Типичный сценарий: вы передали массив в процедуру, процедура добавила в него элементы — и в вызывающем коде массив тоже изменился, хотя вы этого не ожидали. Понимание того, какие типы мутабельны и где платформа копирует значения, а где нет, позволяет писать предсказуемый код и не тратить часы на отладку «самопроизвольно меняющихся» данных.

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

Что такое мутабельность простыми словами

Мутабельный объект — это контейнер, содержимое которого можно менять, не создавая новый объект. Представьте ящик с инструментами: переменная хранит не сам ящик, а его «адрес». Если вы дали адрес коллеге, он видит тот же ящик — положит туда молоток, и вы его тоже увидите. Иммутабельное значение — как надпись на бумажке: чтобы её изменить, нужно написать новую бумажку, старая останется нетронутой.

Во встроенном языке 1С разница проявляется в операции присваивания. Для примитивов присваивание создаёт независимое значение: А = 10; Б = А; А = 20; — переменная Б останется равной 10. Для мутабельных типов присваивание копирует ссылку: Массив1 = Новый Массив; Массив2 = Массив1; — обе переменные указывают на один массив, и Массив2.Добавить(1) изменит содержимое, видимое через Массив1.

Какие типы 1С мутабельны, а какие — нет

Чёткое разделение типов помогает заранее предсказать поведение кода. В таблице ниже собраны основные типы встроенного языка.

ТипМутабельностьЧто происходит при присваивании
ЧислоНетКопируется значение, переменные независимы
СтрокаНетКопируется значение; операции создают новую строку
ДатаНетКопируется значение
БулевоНетКопируется значение
МассивДаКопируется ссылка, объект общий
СтруктураДаКопируется ссылка, объект общий
СоответствиеДаКопируется ссылка, объект общий
ТаблицаЗначенийДаКопируется ссылка, объект общий
СписокЗначенийДаКопируется ссылка, объект общий
ФиксированнаяСтруктура, ФиксированныйМассивНет (защищены от изменений)Попытка изменения вызывает ошибку

Отдельно стоит семейство фиксированных типов. ФиксированнаяСтруктура и ФиксированныйМассив создаются на основе обычных структур и массивов, но после создания их нельзя изменить — платформа выдаст ошибку при попытке добавить или изменить элемент. Это удобный способ защитить данные от случайной модификации, например при передаче параметров между общими модулями.

Объекты базы данных (СправочникОбъект, ДокументОбъект) тоже мутабельны в рамках сеанса: изменения реквизитов видны всем, кто держит тот же объект, до вызова метода Записать. Однако ссылки на объекты (СправочникСсылка) ведут себя как иммутабельные значения — ссылку нельзя «изменить», можно только присвоить другую.

Где мутабельность вызывает ошибки на практике

Самая частая проблема — передача коллекций в процедуры и функции. По умолчанию параметры в 1С передаются по ссылке, и для мутабельных типов это означает: вызываемая процедура работает с тем же самым объектом. Если она очищает таблицу значений или дополняет структуру, вызывающий код получит изменённые данные, даже если слово «Знач» в объявлении параметра не использовалось.

Вторая типичная ситуация — кэширование и повторное использование коллекций. Разработчик один раз формирует структуру параметров, сохраняет её в переменную модуля, а затем в разных процедурах дополняет её под конкретные задачи. В результате в кэше накапливаются «чужие» ключи, и поведение программы начинает зависеть от порядка вызовов. Такие ошибки сложно воспроизвести и отладить, потому что состояние объекта зависит от всей истории работы сеанса.

Третий сценарий — заполнение коллекции одинаковыми объектами в цикле. Если создать структуру до цикла и внутри цикла только менять её поля и добавлять в массив, то в массиве окажется несколько ссылок на одну и ту же структуру: все элементы будут содержать данные последней итерации. Правильное решение — создавать новую структуру внутри цикла.

Типичные ошибки
01
Создание структуры вне цикла и добавление её в массив: все элементы массива ссылаются на один объект и содержат данные последней итерации
02
Передача таблицы значений в процедуру без осознания, что процедура изменит исходную таблицу вызывающего кода
03
Хранение изменяемой структуры в переменной модуля: накопление лишних ключей и зависимость результата от порядка вызовов

Как передать мутабельное значение без побочных эффектов

Первый способ — ключевое слово Знач в объявлении параметра. Оно заставляет платформа создать копию значения при вызове. Для массивов и структур копия будет поверхностной: копируется сам контейнер, но вложенные мутабельные объекты остаются общими. Для простых сценариев этого достаточно, но глубокие структуры требуют аккуратности.

Второй способ — явное копирование через сериализацию. Универсальный приём глубокого копирования в 1С — использовать ЗначениеВСтрокуВнутр и ЗначениеИзСтрокиВнутр: объект преобразуется во внутреннее строковое представление и восстанавливается обратно как полностью независимая копия. Способ работает для большинства коллекций, но заметно медленнее простого присваивания, поэтому применять его стоит только там, где копия действительно нужна.

Третий подход — проектирование без общего состояния. Функция вместо изменения переданной коллекции создаёт и возвращает новую. Такой стиль делает код предсказуемым: вызывающая сторона всегда видит, что результат приходит через возвращаемое значение, а исходные данные не тронуты. Для таблиц значений удобен метод Скопировать(), который создаёт новую таблицу с теми же данными.

Как получить независимую копию коллекции
  1. 1
    Определите, нужна ли копия вообще: если процедура только читает данные, копирование не требуется
  2. 2
    Для простого случая добавьте Знач в объявление параметра процедуры
  3. 3
    Для таблицы значений используйте метод Скопировать() — он создаёт новую независимую таблицу
  4. 4
    Для глубокой копии вложенных структур примените пару ЗначениеВСтрокуВнутр / ЗначениеИзСтрокиВнутр
  5. 5
    Проверьте результат: измените копию и убедитесь, что оригинал не изменился

Иммутабельность строк и производительность

Иммутабельность строк влияет не только на логику, но и на скорость работы. Каждая операция конкатенации Строка = Строка + Фрагмент; создаёт новую строку и копирует всё накопленное содержимое. В цикле из тысяч итераций это приводит к квадратичному росту объёма копируемых данных и заметному падению производительности при сборке больших текстов — например, XML-документов или длинных запросов.

Правильная альтернатива — собирать части в массив и соединять их одной операцией через СтрСоединить(), либо использовать специализированные объекты: ЗаписьXML, ЗаписьJSON, ТекстовыйДокумент. Эти объекты ведут внутренний буфер и не копируют весь текст при каждом добавлении. Тот же принцип действует при построении текста запроса: добавляйте фрагменты в массив и соединяйте в конце.

Если код собирает строку из более чем нескольких десятков фрагментов в цикле, замена конкатенации на массив со СтрСоединить() обычно даёт заметный прирост скорости без изменения логики программы. Это одна из самых дешёвых оптимизаций во встроенном языке.
ПЗ
Практическое замечание

Фиксированные типы как защита от изменений

Когда нужно гарантировать, что коллекция не будет изменена нигде по цепочке вызовов, используйте фиксированные аналоги. ФиксированнаяСтруктура создаётся конструктором Новый ФиксированнаяСтруктура(ОбычнаяСтруктура), после чего любая попытка добавить, удалить или изменить свойство вызовет исключение. Это превращает скрытые побочные эффекты в явные ошибки, которые сразу видно при тестировании.

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

Как проверить код на проблемы с мутабельностью

Признак проблемы — данные «меняются сами» между двумя точками программы, где явных присваиваний нет. Чтобы локализовать источник, пройдите по цепочке вызовов и отметьте каждую процедуру, получающую коллекцию параметром без Знач. Любая из них потенциально может менять объект. В отладчике удобно сравнивать содержимое коллекции до и после вызова подозрительной процедуры.

Полезный приём — проверка идентичности объектов. Две переменные, указывающие на один массив, можно выявить, добавив уникальный маркер через одну переменную и проверив его наличие через другую. Если маркер виден в обеих — объект общий. На этапе код-ревью обращайте внимание на присваивания коллекций между переменными модуля и локальными переменными: такие места почти всегда создают скрытую связность.

Контрольные точки

Как проверить результат

Переменные после присваивания коллекции
Норма

Изменение одной не влияет на другую (копия создана осознанно)

Тревожный признак

Обе переменные показывают одни и те же изменения

Параметры процедур с коллекциями
Норма

Изменяющие процедуры задокументированы или используют Знач

Тревожный признак

Процедура молча меняет переданную коллекцию

Сборка строк в цикле
Норма

Используется массив и СтрСоединить или объект записи

Тревожный признак

Конкатенация в цикле с сотнями итераций

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

Почему после вызова процедуры мой массив оказался пустым?

Процедура, скорее всего, вызвала метод Очистить() для переданного параметра. Поскольку массив передаётся по ссылке, очистился ваш исходный объект. Решения: добавить Знач в объявление параметра, передавать копию массива или пересмотреть логику процедуры, чтобы она не изменяла входные данные.

Чем отличается Скопировать() у таблицы значений от простого присваивания?

Присваивание копирует только ссылку: обе переменные работают с одной таблицей. Метод Скопировать() создаёт новую таблицу значений с теми же колонками и строками, и изменения в ней не затрагивают оригинал. Метод также позволяет скопировать только отобранные строки.

Можно ли сделать структуру полностью неизменяемой вместе с вложенными объектами?

Напрямую — только зафиксировав каждый уровень: вложенные структуры и массивы тоже должны быть фиксированными. Автоматической «глубокой фиксации» в платформе нет, поэтому вложенные коллекции фиксируют при построении объекта, снизу вверх.

Влияет ли мутабельность на работу с запросами и СКД?

Результат запроса и выборки иммутабельны для чтения в обычном смысле — вы обходите их, но не редактируете. А вот выгруженная через Выгрузить() таблица значений — обычный мутабельный объект, и все правила про ссылки и копии к ней применимы в полной мере.

Когда копирование коллекций вредит производительности?

Глубокое копирование через ЗначениеВСтрокуВнутр и массовое использование Знач для больших таблиц создают лишнюю работу. Если процедура только читает данные, копия не нужна. Копируйте осознанно: только там, где вызываемый код действительно изменяет объект, а вызывающий должен сохранить исходное состояние.

Почему в цикле все элементы массива структур получились одинаковыми?

Структура создана один раз до цикла, а в цикле в массив добавляются ссылки на неё же. Все элементы указывают на один объект с данными последней итерации. Перенесите создание структуры оператором Новый Структура внутрь тела цикла.

Итог

Что важно запомнить

В 1С мутабельны массивы, структуры, соответствия, таблицы и списки значений: они передаются и присваиваются по ссылке. Примитивы иммутабельны. Защищайтесь от побочных эффектов через Знач, метод Скопировать(), фиксированные типы и стиль «функция возвращает новую коллекцию», а длинные строки собирайте массивом, а не конкатенацией в цикле.