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

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

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

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

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

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

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

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

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

Вторая группа — ссылочные по поведению составные типы: массив, структура, фиксированная структура (с оговоркой), соответствие, таблица значений, дерево значений, список значений, COM-объекты, объекты данных (ДокументОбъект, СправочникОбъект и другие). Присваивание такой переменной создаёт вторую ссылку на тот же объект.

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

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

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

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

bsl
ТЗ1 = Новый ТаблицаЗначений;
ТЗ1.Колонки.Добавить("Номенклатура");
ТЗ2 = ТЗ1; // это НЕ копия, а вторая ссылка
ТЗ2.Добавить(); // строка появится и в ТЗ1
Сообщить(ТЗ1.Количество()); // выведет 1

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

Практическая польза: где мутабельность работает на вас

Мутабельность — не дефект, а осознанное поведение платформы, и она даёт реальные преимущества. Первое — производительность: передача большой таблицы значений в процедуру не требует копирования тысяч строк. Механизм передаёт ссылку, и работа идёт с исходными данными без лишних затрат памяти.

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

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

Типичные ошибки и как их избежать

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

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

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

Типичные ошибки
01
Присваивание ТЗ2 = ТЗ1 с ожиданием копии — обе переменные ссылаются на одну таблицу, изменения дублируются. Используйте ТЗ1.Скопировать().
02
Ожидание, что Знач в параметре защитит таблицу от изменений — копируется только ссылка, содержимое меняется. Для защиты передавайте копию объекта.
03
Модификация массива или соответствия во время обхода в цикле Для Каждого — пропуск элементов или ошибка. Обходите копию или идите по индексам с конца.
04
Повторное использование структуры-параметра без очистки — в следующий вызов уходят устаревшие данные предыдущего.

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

У большинства составных типов есть метод Скопировать(), но его поведение различается. У таблицы значений Скопировать() создаёт полную независимую копию со всеми строками. У массива Скопировать() тоже создаёт новый массив, но элементы внутри — те же самые объекты, если элементы сами мутабельны. Это так называемое неглубокое копирование.

У структуры метода Скопировать() нет — для копирования создают новую структуру и переносят ключи, либо используют сериализацию. У соответствия ситуация аналогична. Если нужна глубокая копия вложенных структур (структура внутри структуры), придётся писать рекурсивную процедуру или использовать обход через JSON/внутреннее представление.

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

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

Мутабельность объектов метаданных: отдельный случай

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

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

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

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

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

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

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

Состояние таблицы до и после вызова процедуры
Норма

Количество строк и содержимое совпадают, если процедура не должна менять данные

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

Строки добавились, удалились или изменились без явного возврата значения

Поведение при передаче копии объекта
Норма

Ошибка исчезла — подтверждено нежелательное изменение параметра

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

Ошибка осталась — причина в другом месте кода

Повторный вызов процедуры с той же структурой
Норма

Результат идентичен первому вызову

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

Результат зависит от предыдущего вызова — структура накапливает состояние

FAQ

Чем мутабельный тип в 1С отличается от ссылочного типа?

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

Почему строка в 1С не считается мутабельной?

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

Защищает ли Знач в параметре процедуры таблицу значений от изменений?

Нет. Ключевое слово Знач копирует значение параметра, но для таблицы значений «значением» является ссылка на объект. Внутри процедуры работает копия ссылки, указывающая на ту же таблицу. Чтобы реально защитить данные, передавайте в процедуру результат метода Скопировать().

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

Штатного метода глубокого копирования у структуры нет. Варианты: написать рекурсивную функцию обхода с созданием новых структур; сериализовать структуру в JSON и прочитать обратно (подходит, если все значения сериализуемы); использовать ЗначениеВСтрокуВнутр и ЗначениеИзСтрокиВнутр для платформенной сериализации. Выбор зависит от состава данных и требований к переносимости.

Можно ли изменить фиксированную структуру?

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

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

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

Итог

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

Мутабельные типы в 1С — массив, структура, соответствие, таблица значений и объекты метаданных — передаются и присваиваются по ссылке, поэтому изменения видны всем переменным. Ключевое слово Знач не защищает содержимое таких объектов. Для независимой копии используйте Скопировать(), а изменение параметров внутри процедур всегда делайте осознанно и документируйте.