В практике разработки на платформе 1С:Предприятие 8 часто возникает задача создания копии массива. На первый взгляд задача кажется тривиальной, однако начинающие разработчики часто сталкиваются с проблемой передачи ссылки на объект вместо создания его физической копии. Если мы просто напишем НовыйМассив = СтарыйМассив;, то обе переменные будут указывать на один и тот же объект в памяти. Изменение одного массива неизбежно приведет к изменению другого. Рассмотрим подробнее, как правильно выполнять копирование в различных ситуациях.
Это классический и самый прозрачный метод. Мы создаем новый объект Массив и последовательно добавляем в него элементы из исходной коллекции. Разберем этот процесс по шагам:
КопияМассива = Новый Массив;
Для Каждого Элемент Из ИсходныйМассив Цикл
КопияМассива.Добавить(Элемент);
КонецЦикла;
Этот способ идеально подходит для массивов, содержащих примитивные типы данных (строки, числа, даты, булево) или ссылки на объекты базы данных. Однако проанализируем ситуацию: если элементами массива являются другие коллекции (например, структуры или другие массивы), то в новый массив будут скопированы только ссылки на эти коллекции. Это называется поверхностным копированием.
Если ваша конфигурация построена на базе БСП (что является стандартом для современных решений 1С), нам доступны готовые инструменты. В модуле ОбщегоНазначения существуют функции, которые берут на себя рутину по обходу коллекции.
Ранее широко использовалась функция:
ОбщегоНазначения.СкопироватьУниверсальнуюКоллекцию(КоллекцияИсходная)
В актуальных версиях БСП (начиная с 2024 года и ранее) рекомендуется использовать более мощный инструмент для создания полной копии:
// Создает глубокую копию массива или другой коллекции
МассивКопия = ОбщегоНазначения.СкопироватьРекурсивно(ИсходныйМассив);
Преимущество этого метода в том, что он умеет обрабатывать вложенные структуры, создавая новые экземпляры для каждого уровня вложенности.
Существует элегантный и лаконичный способ копирования через промежуточный объект СписокЗначений. Этот метод часто используется в типовых конфигурациях для быстрого «перекладывания» данных.
Список = Новый СписокЗначений;
Список.ЗагрузитьЗначения(ИсходныйМассив);
КопияМассива = Список.ВыгрузитьЗначения();
Проанализируем этот механизм: метод ЗагрузитьЗначения быстро заполняет список, а ВыгрузитьЗначения создает совершенно новый массив. Это поверхностное копирование, но оно записывается короче, чем цикл Для Каждого.
Если нам необходимо гарантированно получить независимую копию со всеми вложенными данными (структурами, соответствиями, массивами), можно прибегнуть к механизму сериализации. Платформа 1С имеет встроенные функции для преобразования объекта в специальную внутреннюю строку формата 1С.
КопияМассива = ЗначениеИзСтрокиВнутр(ЗначениеВСтрокуВнутр(ИсходныйМассив));
Важный нюанс: хотя этот метод работает быстро и эффективно, формат ЗначениеВСтрокуВнутр считается устаревшим и не рекомендуется для использования в кроссплатформенных решениях (например, если планируется работа на Linux-серверах с определенными настройками). Однако для большинства задач внутри Windows-окружения он остается «выручалочкой» для создания клонов сложных структур.
Интересный способ создания копии заключается в использовании типа ФиксированныйМассив. Этот тип данных предназначен для коллекций, которые нельзя изменять. Но мы можем использовать его как промежуточный этап для получения обычного изменяемого массива.
// Сначала создаем фиксированную копию, затем на ее основе — новый массив
КопияМассива = Новый Массив(Новый ФиксированныйМассив(ИсходныйМассив));
Здесь конструктор Новый Массив() принимает на вход другую коллекцию и создает на ее основе новый независимый объект.
Для максимально надежного «глубокого» копирования, которое гарантированно разрывает связи между объектами, можно использовать механизмы передачи данных между клиентом и сервером. Помещение во временное хранилище фактически сериализует объект в двоичные данные.
Адрес = ПоместитьВоВременноеХранилище(ИсходныйМассив);
КопияМассива = ПолучитьИзВременногоХранилища(Адрес);
Выясним причину популярности этого метода: он работает стабильнее, чем XML или JSON сериализация, так как использует оптимизированные механизмы самой платформы. Это отличный способ клонировать массив со сложным деревом вложенности.
Рассмотрим пример из практики. Представьте, что вы работаете с формой, где пользователь выбирает строки в списке (Элементы.Список.ВыделенныеСтроки). Вам нужно обработать этот массив дважды, но в каждом случае по разным правилам (например, для разных структур документов). Если вы начнете удалять элементы из оригинального массива ВыделенныеСтроки, они пропадут и из интерфейса, и для последующей обработки. В таких случаях создание копии — единственный верный путь.
Также копирование критично при работе с ТаблицейЗначений. Если вы помещаете один и тот же массив в разные строки колонки ТЗ без копирования, то изменение массива в одной строке магическим образом изменит его во всех остальных, так как все строки будут хранить ссылку на один и тот же объект в памяти.
Таким образом, выбор метода зависит от состава данных в вашем массиве и требований к производительности системы. В большинстве повседневных задач программисту 1С достаточно использовать ОбщегоНазначения.СкопироватьРекурсивно или цикл, если массив содержит только простые ссылки или значения.