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

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

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

1. Примитивные типы данных: что может вернуть функция

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

В 1С:Предприятие 8 к примитивам относятся:

  • 🔢 Число (Число) — например, 42 или 3.14. Используется для математических операций, индексов, количественных показателей.
  • 📝 Строка (Строка) — любой текст в кавычках: "Привет" или "Код: 123".
  • 🗓️ Дата (Дата) — например, '2026-12-31'. Может включать время ('2026-12-31 23:59:59').
  • Булево (Булево) — только Истина или Ложь. Часто возвращается функциями-проверками, например СтрокаПустая().
  • Неопределено (Неопределено) — сигнализирует об отсутствии значения. Не путайте с Null (о нём ниже)!

Пример функции, возвращающей примитив:

Функция ПолучитьСкидку(СуммаЗаказа)

Если СуммаЗаказа > 10000 Тогда

Возврат 0.1; // Число

Иначе

Возврат "Скидка не предоставляется"; // Строка

КонецЕсли;

КонецФункции

⚠️ Внимание: Если функция должна вернуть число, но в каком-то случае возвращает строку (как в примере выше), это может привести к ошибке при дальнейших вычислениях. Всегда проверяйте тип возвращаемого значения!

Особняком стоит тип Null. Он используется в запросах и означает "отсутствие данных в базе". Например, если запрос не нашёл записей, поле может вернуть Null. В отличие от Неопределено, Null — это значение базы данных, а не языка .

📊 Какой примитивный тип вы используете чаще всего в возвращаемых значениях?
Число
Строка
Дата
Булево
Неопределено

2. Сложные типы: объекты, коллекции и структуры

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

Рассмотрим основные варианты:

  • 📊 Массив (Массив) — упорядоченный набор элементов. Например, Массив = Новый Массив(); Массив.Добавить(1); Массив.Добавить("Два").
  • 🔑 Структура (Структура) — набор пар "ключ-значение". Удобна для возврата нескольких связанных данных: Результат = Новый Структура("Имя, Возраст", "Иван", 30).
  • 📋 Соответствие (Соответствие) — аналогично структуре, но с динамическими ключами.
  • 🏢 Объекты метаданных — справочники, документы, регистры. Например, функция может вернуть объект СправочникОбъект.Контрагенты.НайтиПоНаименованию("ООО Ромашка").
  • 🔄 Запрос (Запрос) — функция может вернуть объект запроса для дальнейшего выполнения: Возврат Новый Запрос("ВЫБРАТЬ..").

Пример функции, возвращающей структуру:

Функция ПолучитьДанныеКлиента(ИдКлиента)

Клиент = Справочники.Клиенты.НайтиПоИд(ИдКлиента);

Если Клиент = Неопределено Тогда

Возврат Неопределено;

КонецЕсли;

Возврат Новый Структура(

"Имя, Email, Баланс",

Клиент.Наименование,

Клиент.ЭлектроннаяПочта,

Клиент.Баланс

);

КонецФункции

Особое внимание уделите объектам метаданных. Если функция возвращает, например, документ, убедитесь, что он не заблокирован другим пользователем. Иначе при попытке записи возникнет ошибка.

💡

Используйте аннотации в коде, чтобы явно указать, какой тип возвращает функция. Например: // @Возвращает Структура|Неопределено. Это поможет другим разработчикам и упростит поддержку кода.

3. Ошибки и исключения: когда функция "возвращает" проблему

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

Распространённые источники ошибок:

  • 🔍 Поиск несуществующего объекта — например, Справочники.Номенклатура.НайтиПоКоду("99999") вернёт Неопределено, но если далее попробовать вызвать метод у этого значения, будет ошибка.
  • 🔒 Нарушение прав доступа — попытка записать документ без прав или изменить заблокированный объект.
  • 📥 Ошибки ввода-вывода — проблемы при работе с файлами или внешними источниками данных.
  • 🧮 Математические ошибки — деление на ноль, переполнение чисел.

Пример обработки исключения:

Функция Разделить(Числитель, Знаменатель)

Попытка

Если Знаменатель = 0 Тогда

ВызватьИсключение "Деление на ноль!";

КонецЕсли;

Возврат Числитель / Знаменатель;

Исключение

ЗаписатьЖурналРегистрации(ОписаниеОшибки(), УровеньЖурналаОшибка);

Возврат Неопределено;

КонецПопытки;

КонецФункции

⚠️ Внимание: Если функция генерирует исключение, но оно не обрабатывается, выполнение кода прервётся. Это может привести к несохранённым данным или "подвисанию" сеанса. Всегда проверяйте критические участки на наличие Попытка..Исключение.

Иногда функции специально возвращают Ложь или Неопределено вместо генерации исключения. Например, функция проверки доступности сервера может вернуть Ложь при ошибке подключения. Такой подход упрощает обработку, но требует чёткой документации.

4. Таблица типов возвращаемых значений и их особенности

Для удобства сведем все возможные возвращаемые типы в таблицу с указанием их особенностей и типичных сценариев использования.

Тип данных Пример значения Особенности Типичное использование
Число 100, 3.14 Поддерживает арифметические операции. Может быть целым или дробным. Расчёты, индексы, количественные показатели.
Строка "Привет", "123" Неизменяема. Поддерживает конкатенацию (+). Сообщения, наименования, тексты документов.
Дата '2026-12-31' Может включать время. Поддерживает арифметику дат. Указание периодов, сроков, временных меток.
Булево Истина, Ложь Используется в условиях (Если..). Проверки, флаги, условия выполнения.
Неопределено Неопределено Не является ошибкой, но вызов методов приведёт к исключению. Сигнализация об отсутствии данных или ошибке.
Null Null Возвращается запросами. Требует проверки ЗначениеЗаполнено(). Результаты запросов, поля базы данных.
Массив Новый Массив(1, 2, 3) Динамический размер. Элементы могут быть разных типов. Списки данных, коллекции объектов.

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

💡

Всегда документируйте, какой тип возвращает функция, особенно если это может быть Неопределено или Null. Это сэкономит часы отладки в будущем.

5. Пользовательские объекты и расширения

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

Примеры пользовательских типов:

  • 🧩 Объекты расширений — например, класс МойКалькулятор, определённый в расширении конфигурации.
  • 🖥️ Внешние компоненты — объекты, подключённые через COM или .NET.
  • 📦 Общие модули с экспортными методами — функция может вернуть объект, созданный в другом модуле.

Пример работы с пользовательским объектом:

// В расширении определен класс "КалькуляторНДС"

Функция ПолучитьКалькуляторНДС()

Возврат Новый КалькуляторНДС(); // Возвращает пользовательский объект

КонецФункции

// Использование

Калькулятор = ПолучитьКалькуляторНДС();

СуммаСНДС = Калькулятор.ПосчитатьНДС(1000, 20);

⚠️ Внимание: Если функция возвращает объект из внешней компоненты, убедитесь, что компонента зарегистрирована на клиентском компьютере. Иначе при попытке создания объекта возникнет ошибка.

При работе с расширениями помните, что:

  • Объекты расширений могут иметь свои методы и свойства, не видимые в основной конфигурации.
  • Изменения в расширении не требуют обновления всей конфигурации, но могут сломать существующий код, если сигнатуры методов поменялись.
  • Внешние компоненты могут зависеть от версий библиотек или операционной системы.
Как проверить, поддерживает ли объект метод?

Используйте функцию ТипЗнч(Объект) = "ТипОбъектаИмя" или проверку через ? (Объект.Метод) в отладчике. Например: Если ТипЗнч(МойОбъект) = "МойКалькулятор" Тогда..

6. Оптимизация и лучшие практики

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

Рекомендации по оптимизации:

  • 🚀 Избегайте тяжелых объектов — если функция возвращает большой массив или результат сложного запроса, подумайте, можно ли вернуть только необходимые данные (например, идентификаторы, а не сами объекты).
  • 🔄 Кэшируйте результаты — если функция часто вызывается с одинаковыми параметрами, сохраняйте результат в статической переменной или кэше.
  • 📋 Документируйте возвращаемые типы — даже если это кажется очевидным. Например: // @Возвращает Массив|Неопределено.
  • 🛡️ Проверяйте входные параметры — если функция ожидает число, а получает строку, лучше вернуть ошибку сразу, чем допустить некорректные вычисления.

Пример оптимизированной функции с кэшированием:

Перем мКэшСправочников;

Функция ПолучитьСправочникПоИмени(ИмяСправочника)

Если мКэшСправочников = Неопределено Тогда

мКэшСправочников = Новый Соответствие();

КонецЕсли;

Если мКэшСправочников.СодержитКлюч(ИмяСправочника) Тогда

Возврат мКэшСправочников[ИмяСправочника];

КонецЕсли;

Справочник = Метаданные.Справочники.Найти(ИмяСправочника);

мКэшСправочников.Вставить(ИмяСправочника, Справочник);

Возврат Справочник;

КонецФункции

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

Функция ПолучитьНастройки()

Настройки = Новый Структура();

Настройки.Вставить("Цвет", "Красный");

Настройки.Вставить("Размер", 12);

Возврат Настройки.Скопировать(); // Возвращаем копию!

КонецФункции

7. Отладка и анализ возвращаемых значений

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

Инструменты для отладки:

  • 🐞 Отладчик 1С — установите точку останова на строке Возврат и посмотрите, что именно возвращается.
  • 📄 Журнал регистрации — записывайте возвращаемые значения для анализа: ЗаписатьЖурналРегистрации(Строка(Результат)).
  • 🔍 Функция ТипЗнч() — проверяет тип значения: ТипЗнч(Результат) вернёт "Число", "Строка" и т.д.
  • 📌 Условные точки останова — останавливайте выполнение только если возвращаемое значение соответствует условию (например, Результат = Неопределено).

Пример использования ТипЗнч() для диагностики:

Результат = МояФункция(Параметр);

Если ТипЗнч(Результат) <> "Число" Тогда

Сообщить("Ошибка: функция вернула " + ТипЗнч(Результат) + ", ожидалось Число!");

КонецЕсли;

Если функция возвращает Неопределено или Null, проверьте:

Правильно ли переданы параметры в функцию?

Есть ли в функции блоки Попытка..Исключение, которые "глотнули" ошибку?

Не заблокирован ли возвращаемый объект (например, документ) другим пользователем?

Совпадает ли версия платформы с ожидаемой (некоторые методы могут отсутствовать в старых версиях)?

Проверены ли права доступа на возвращаемый объект?-->

Для анализа сложных объектов (например, результатов запросов) используйте вывод в ТабличныйДокумент:

Процедура ВывестиРезультат(Результат)

ТЗ = Новый ТаблицаЗначений();

ТЗ.Колонки.Добавить("Ключ");

ТЗ.Колонки.Добавить("Значение");

Для Каждого Элемент Из Результат Цикл

Строка = ТЗ.Добавить();

Строка.Ключ = Элемент.Ключ;

Строка.Значение = Элемент.Значение;

КонецЦикла;

ТЗ.Вывести();

КонецПроцедуры

⚠️ Внимание: В многопользовательском режиме отладка может быть затруднена из-за блокировок. Используйте ЖурналРегистрации вместо Сообщить(), чтобы не прерывать работу других пользователей.

FAQ: Частые вопросы о возвращаемых значениях в 1С

Может ли функция в 1С не возвращать ничего?

Нет, любая функция в 1С обязательно возвращает значение. Если явно не указано Возврат, функция вернёт Неопределено. Это отличается от процедур, которые ничего не возвращают.

Как отличить Null от Неопределено?

Null — это значение базы данных, возвращаемое запросами (проверяется через ЗначениеЗаполнено()). Неопределено — это значение языка 1С, означающее "ничего". Например:

РезультатЗапроса = Запрос.Выполнить().Выгрузить();

Если ЗначениеЗаполнено(РезультатЗапроса[0].Поле) Тогда

// Поле не Null

КонецЕсли;

Для Неопределено проверка выглядит так: Если Результат = Неопределено Тогда...

Можно ли вернуть из функции несколько значений?

Да, для этого используйте Структуру или Массив. Например:

Функция ПолучитьДанные()

Возврат Новый Структура("Имя, Возраст", "Иван", 30);

КонецФункции

// Использование

Данные = ПолучитьДанные();

Имя = Данные.Имя;

Возраст = Данные.Возраст;

Что будет, если функция вернёт объект, который потом изменится?

Если функция возвращает ссылку на объект (например, элемент справочника), то изменения этого объекта вне функции отразятся на оригинале. Чтобы избежать побочных эффектов, возвращайте копии объектов или используйте Скопировать() для коллекций.

Пример проблемы:

Функция ПолучитьНастройки()

Настройки = Новый Структура();

Настройки.Вставить("Тема", "Темная");

Возврат Настройки; // Возвращается оригинал!

КонецФункции

Настройки = ПолучитьНастройки();

Настройки.Тема = "Светлая"; // Изменится оригинальная структура!

Как вернуть ошибку из функции?

Есть два подхода:

  1. Генерация исключения — если ошибка критическая и дальнейшее выполнение невозможно:
    Если УсловиеОшибки Тогда
    

    ВызватьИсключение "Описание ошибки";

    КонецЕсли;

  2. Возврат специального значения — если ошибка обрабатываемая (например, Ложь или структура с флагом ошибки):
    Если УсловиеОшибки Тогда
    

    Возврат Новый Структура("Успех, Сообщение", Ложь, "Текст ошибки");

    КонецЕсли;

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