Как правильно проверить, есть ли элементы в Соответствии, или оно пустое?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Стандартный способ: метод Количество()

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

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


// Предположим, это наше соответствие с рабочими столами
АктивныеСтолы = Новый Соответствие;

// ... в процессе работы программы оно как-то заполняется ...
// АктивныеСтолы.Вставить(Пользователь1, ДанныеСтола1);

// Проверка перед закрытием программы
Если АктивныеСтолы.Количество() = 0 Тогда
    Сообщить("Все рабочие столы закрыты. Программу можно закрывать.");
    // Здесь может быть код для закрытия программы
Иначе
    Сообщить("Обнаружены незакрытые рабочие столы! Количество: " + АктивныеСтолы.Количество());
    // Здесь может быть код, прерывающий закрытие и выводящий предупреждение
КонецЕсли;

Этот подход является идеальным по нескольким причинам:

  1. Читаемость: Код Если МоеСоответствие.Количество() > 0 недвусмысленно говорит о намерении программиста — "если в соответствии есть хотя бы один элемент".
  2. Простота: Это самый короткий и лаконичный способ достичь цели.
  3. Производительность: Как мы разберем ниже, это самый быстрый способ.

Вопросы производительности: Количество() против перебора в цикле

Иногда может возникнуть предположение, что для очень больших коллекций (например, с миллионами элементов) вызов метода Количество() может быть ресурсоемкой операцией, и что быстрее было бы запустить цикл и прервать его на первом же элементе. Для платформы 1С:Предприятие 8 это утверждение неверно.

Давайте разберемся, как это работает "под капотом":

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

А вот организация цикла, даже с немедленным выходом, — более сложный процесс:


// Неэффективный способ проверки на пустоту
СоответствиеНеПустое = Ложь;
Для Каждого Элемент Из ОгромноеСоответствие Цикл
    СоответствиеНеПустое = Истина;
    Прервать; // Выходим на первом же элементе
КонецЦикла;

Если СоответствиеНеПустое Тогда
    // ...
КонецЕсли;

Что здесь происходит с точки зрения системы:

  1. Создается специальный объект-итератор для обхода коллекции.
  2. Происходит извлечение первого элемента.
  3. Выполняются операции внутри цикла (присваивание, вызов Прервать).

Все это требует больше системных ресурсов, чем простое чтение одного числового поля. Поэтому вывод однозначен: всегда используйте Количество() для проверки коллекции на пустоту.

Контекст перехода с 1С 7.7 и "боязнь новых объектов"

В обсуждении на форуме была упомянута "боязнь этих объектов" после работы с 1С 7.7. Это очень характерное ощущение для многих разработчиков того времени, и оно имеет под собой веские основания.

В платформе 1С 7.7 не было прямого и настолько гибкого аналога объекта Соответствие, где в качестве ключа мог выступать любой тип данных (например, ссылка на документ или элемент справочника). Задачи, которые сегодня элегантно решаются с помощью Соответствие, тогда требовали "обходных путей":

Поэтому переход на платформу 8.х с ее богатой и унифицированной объектной моделью требовал привыкания и изучения новых подходов, что и вызывало начальные трудности.

Важное уточнение: пустое соответствие и соответствие с "пустыми" значениями

Следует четко различать два понятия:

  1. Пустое соответствие — это коллекция, в которой нет ни одной пары "Ключ-Значение". Именно это мы и проверяем с помощью Количество() = 0.
  2. Непустое соответствие, содержащее "пустые" значения — это коллекция, где есть элементы, но их значения могут быть неинициализированными или пустыми.

В 1С существует несколько видов "пустых" значений:

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

Посмотрим на пример, где нужно обработать только те элементы соответствия, у которых значение является заполненной ссылкой на контрагента.


// Соответствие может содержать разные значения
МоиДанные = Новый Соответствие;
МоиДанные.Вставить("Заказ1", Справочники.Контрагенты.НайтиПоКоду("001"));
МоиДанные.Вставить("Заказ2", Неопределено); // Значение не было установлено
МоиДанные.Вставить("Заказ3", Справочники.Контрагенты.ПустаяСсылка()); // Значение - пустая ссылка

Если МоиДанные.Количество() > 0 Тогда
    Сообщить("В соответствии есть данные, начинаем обработку...");
    Для Каждого КлючЗначение Из МоиДанные Цикл
        
        ТекущийКонтрагент = КлючЗначение.Значение;
        
        // Проверяем, что значение - это ссылка на контрагента и она не пустая
        Если ТипЗнч(ТекущийКонтрагент) = Тип("СправочникСсылка.Контрагенты") И НЕ ТекущийКонтрагент.Пустая() Тогда
            Сообщить("Обрабатываем заказ '" + КлючЗначение.Ключ + "' для контрагента: " + ТекущийКонтрагент);
            // ... здесь основная логика работы ...
        Иначе
            Сообщить("Пропускаем заказ '" + КлючЗначение.Ключ + "', так как контрагент не указан или указан некорректно.");
        КонецЕсли;
        
    КонецЦикла;
Иначе
    Сообщить("Нет данных для обработки.");
КонецЕсли;

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

← На главную