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