Разработка и Конфигурация · 10 мин
Как передать массив в функцию 1С
Как передать массив в функцию или процедуру 1С: передача по ссылке и по значению, Знач, примеры кода, типичные ошибки и проверка результата.
Передача массива в функцию или процедуру — одна из базовых операций во встроенном языке 1С, но у неё есть важные особенности. Массив в 1С является ссылочным типом: по умолчанию в функцию передаётся не копия данных, а ссылка на тот же объект. Это значит, что изменения массива внутри вызванной функции будут видны и в вызывающем коде, если явно не указать иное.
Такое поведение часто становится источником скрытых ошибок: разработчик меняет массив внутри функции «для удобства», а потом долго ищет, почему исходная коллекция внезапно изменилась. Понимание механизма передачи параметров и ключевого слова «Знач» позволяет контролировать это поведение осознанно.
Ниже разобраны основные способы объявления параметров, передача по ссылке и по значению, работа с массивами внутри функции, типичные ошибки и способы проверить результат. Примеры приведены для управляемых форм и обычных модулей — синтаксис одинаковый.
Как объявить функцию с параметром-массивом
Синтаксис объявления ничем не отличается от передачи любого другого значения. Параметр указывается в скобках после имени функции, тип не объявляется — 1С использует слабую типизацию, поэтому в параметр можно передать массив любой структуры.
Функция НайтиМаксимум(МассивЧисел) Экспорт
Если МассивЧисел.Количество() = 0 Тогда
Возврат Неопределено;
КонецЕсли;
Максимум = МассивЧисел[0];
Для Каждого Элемент Из МассивЧисел Цикл
Если Элемент > Максимум Тогда
Максимум = Элемент;
КонецЕсли;
КонецЦикла;
Возврат Максимум;
КонецФункции
Вызов такой функции выглядит стандартно: создаёте массив, заполняете его и передаёте переменную в вызов. Важно, что переменная должна быть именно массивом — если передать, например, структуру или строку, обращение по индексу вызовет ошибку исполнения.
Данные = Новый Массив;
Данные.Добавить(10);
Данные.Добавить(42);
Данные.Добавить(7);
Результат = НайтиМаксимум(Данные); // 42
Передача по ссылке: поведение по умолчанию
Когда параметр объявлен без модификаторов, в функцию передаётся ссылка на тот же объект массива. Любые методы, изменяющие коллекцию — Добавить(), Удалить(), Очистить(), присваивание по индексу — затронут оригинал. Это удобно, когда функция специально предназначена для заполнения или модификации массива.
Процедура ДополнитьМассив(МассивПриемник) Экспорт
МассивПриемник.Добавить("Новый элемент");
КонецПроцедуры
Список = Новый Массив;
ДополнитьМассив(Список);
// Список теперь содержит 1 элемент
Такой подход экономит память: копия данных не создаётся, что заметно на больших массивах с тысячами элементов. Но требует дисциплины: функция, которая по смыслу должна только читать данные, не должна их менять. Если функция возвращает результат вычислением, а не модификацией, лучше не трогать входной массив вовсе.
Передача по значению через «Знач»
Ключевое слово «Знач» перед именем параметра заставляет платформу создать копию массива в момент вызова. Функция работает с копией, и исходный массив остаётся нетронутым независимо от того, что происходит внутри.
Процедура ОтсортироватьКопию(Знач МассивДанных) Экспорт
// изменения не затронут исходный массив
КонецПроцедуры
У этого способа есть две цены. Во-первых, копирование большого массива занимает время и память. Во-вторых, копируется сам массив, но не вложенные объекты: если элементами являются структуры или другие массивы, они по-прежнему передаются по ссылке. Изменение вложенной структуры внутри функции отразится на оригинале.
Практическое правило: используйте «Знач», когда функция должна модифицировать коллекцию для своих внутренних нужд (например, отсортировать для поиска), а вызывающий код рассчитывает на неизменность данных. Если функция только читает — «Знач» избыточен и лишь замедляет работу.
Сравнение вариантов
Быстро, функция может заполнять и менять массив. Риск: случайное изменение исходных данных.
Исходный массив защищён от изменений. Минус: затраты на копирование, вложенные объекты всё равно по ссылке.
Функция создаёт и возвращает новый массив, не трогая входной. Наиболее предсказуемый стиль для функций-преобразователей.
Заполнение массива внутри процедуры
Частый сценарий — процедура, которая заполняет переданный ей массив. Здесь передача по ссылке работает на вас: создаёте пустой массив, передаёте в процедуру, после вызова он заполнен.
Процедура ПолучитьСписокКонтрагентов(МассивРезультат) Экспорт
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Справочник.Контрагенты");
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
МассивРезультат.Добавить(Выборка.Ссылка);
КонецЦикла;
КонецПроцедуры
Альтернатива, которая считается более надёжным стилем, — функция, возвращающая новый массив. Тогда вызывающий код явно получает результат через присваивание, и не возникает вопросов, изменилась ли переданная переменная. Для нового кода предпочтительнее именно возврат значения, а заполнение параметра оставить для случаев, когда процедура дополняет уже существующую коллекцию.
- 1Определите, должна ли функция менять исходный массив
- 2Если не должна — добавьте «Знач» перед параметром или верните новый массив
- 3Объявите параметр в сигнатуре функции и задокументируйте ожидаемый тип в комментарии
- 4В начале функции проверьте ТипЗнч(Параметр) = Тип("Массив") при внешних вызовах
- 5Вызовите функцию, передав переменную-массив
- 6Проверьте, что исходный массив после вызова в ожидаемом состоянии
Особенности: сервер, клиент и экспортные функции
При передаче массива между клиентом и сервером в управляемом приложении данные сериализуются — фактически создаётся копия. Поэтому изменение массива на сервере не вернётся на клиент автоматически, даже если параметр объявлен без «Знач». Результат нужно возвращать явно через Возврат или передавать в обе стороны заново.
Ещё одно ограничение: в директиве «&НаКлиенте» нельзя объявить параметр с «Знач» для экспортных процедур и функций в некоторых контекстах — платформа выдаст ошибку компиляции. Если нужна изоляция данных на клиенте, создавайте копию массива вручную внутри тела функции.
Также учитывайте, что массивы, содержащие значения, недоступные на тонком клиенте (например, объекты запросов), не смогут быть переданы с сервера на клиент — передавайте только простые типы, ссылки, структуры и вложенные массивы.
Типичные ошибки и как их избежать
Самая распространённая ошибка — неожиданная модификация исходного массива. Функция сортирует или фильтрует коллекцию «для удобства», а вызывающий код дальше работает с уже изменёнными данными. Лечится либо «Знач», либо созданием нового массива внутри функции.
Вторая ошибка — передача не массива. Из-за слабой типизации функция примет любое значение, а ошибка всплывёт только при обращении по индексу. Для экспортных функций общих модулей полезно добавлять проверку типа в начале тела и возвращать осмысленный результат или вызывать исключение с понятным текстом.
Третья группа ошибок связана с вложенностью: разработчик думает, что «Знач» защитил всё, но меняет структуру внутри массива — и оригинал портится. Помните: глубокое копирование платформа не выполняет, при необходимости его делают вручную циклом.
Как проверить результат
После вызова функции убедитесь в двух вещах: что результат работы корректен и что исходный массив в ожидаемом состоянии. Проще всего это сделать через «Сообщить» или отладчик: выведите Количество() исходного массива до и после вызова.
Для проверки идентичности объектов можно сравнить содержимое поэлементно в цикле. Если массивы большие, достаточно проверить количество элементов и несколько контрольных позиций — первый, последний и элемент из середины.
Как проверить результат
Совпадает с ожиданием (не изменилось для функций-читателей)
Изменилось, хотя функция должна была только читать
Массив ожидаемого размера с корректными элементами
Неопределено, пустой массив или элементы неверного типа
Поля вложенных структур не изменились
Поля изменились — копия была неглубокой
Частые вопросы
Можно ли передать массив как параметр по умолчанию?
Нет, значения по умолчанию для параметров в 1С могут быть только простыми литералами (число, строка, Неопределено). Обходной путь: объявить параметр со значением Неопределено и в начале функции проверить — если Неопределено, создать новый массив.
Как передать в функцию массив структур?
Точно так же, как обычный массив — тип элементов не ограничен. Учтите только, что структуры внутри массива передаются по ссылке: изменение полей структуры внутри функции затронет оригинал даже при использовании «Знач» для самого массива.
Что быстрее: передача по ссылке или через «Знач»?
Передача по ссылке быстрее, так как копирования не происходит. На маленьких массивах разница незаметна, но при тысячах элементов и частых вызовах копирование даёт ощутимые накладные расходы. Используйте «Знач» только когда защита исходных данных действительно нужна.
Почему изменения массива на сервере не видны на клиенте?
При клиент-серверном вызове параметры сериализуются и передаются копиями. Изменённый на сервере массив нужно вернуть через Возврат функции либо присвоить результат на клиенте повторно. Это нормальное поведение платформы, а не ошибка.
Как передать массив в функцию другого общего модуля?
Никаких отличий: вызываете экспортную функцию по имени модуля, например РаботаСДанными.Обработать(МойМассив). Правила передачи по ссылке и по значению действуют одинаково в пределах одного контекста исполнения.
Что важно запомнить
Массив передаётся в функцию 1С как обычный параметр, по умолчанию — по ссылке, поэтому изменения внутри функции видны снаружи. Для защиты исходных данных используйте «Знач», помня, что вложенные объекты не копируются. Между клиентом и сервером массив всегда передаётся копией — результат возвращайте явно. Самый предсказуемый стиль: функция создаёт и возвращает новый массив, не меняя входной.