Мы рассмотрим подробно проблему, которая возникла у пользователей 1С:Розницы (2.3.8.22) после обновления платформы до версии 8.3.20.1996. Суть ошибки заключается в появлении сообщения "Недопустимое значение" при попытке работы с коллекцией типа ФиксированныйМассив. Эта ситуация часто ставит в тупик разработчиков, поскольку она связана с изменением поведения платформы и требует глубокого понимания принципов работы с неизменяемыми коллекциями.
Проблема проявлялась в следующем контексте:
Недопустимое значение {ОбщийМодуль.ОбщегоНазначенияРТ.Модуль(1019)}:ПараметрыВыбора = Новый ФиксированныйМассив(МассивДляВнешнихОбработок);
{Справочник.СкидкиНаценки.Форма.ФормаЭлемента.Форма(117)}:ОбщегоНазначенияРТ.УдалитьПараметрыВыбораРасширений(Элементы.ВнешняяОбработка.ПараметрыВыбора);
по причине: Недопустимое значение
Данная ошибка возникает в процедуре УдалитьПараметрыВыбораРасширений, которая предназначена для фильтрации элементов коллекции ПараметрыВыбора. Давайте детально проанализируем исходный код этой процедуры и разберем причины возникновения ошибки.
Рассмотрим исходный код процедуры УдалитьПараметрыВыбораРасширений, как она была представлена до исправления:
// Удаляет устаревшие параметры выбора
// Параметры:
// ПараметрыВыбора - Фиксированные массив
Процедура УдалитьПараметрыВыбораРасширений(ПараметрыВыбора) Экспорт
Если ПараметрыВыбора.Количество > 0 Тогда
МассивДляВнешнихОбработок = Новый Массив;
СтрокаПоиска = НСтр("ru = ''");
Для каждого ПараметрВыбора Из ПараметрыВыбора Цикл
Если СтрНайти(ПараметрВыбора.Значение, СтрокаПоиска) = 0 Тогда
МассивДляВнешнихОбработок.Добавить(ПараметрВыбора.Значение);
КонецЕсли;
КонецЦикла;
ПараметрыВыбора = Новый ФиксированныйМассив(МассивДляВнешнихОбработок);
КонецЕсли;
КонецПроцедуры
Давайте разберем эту процедуру по шагам и выясним, почему она начала выдавать ошибку "Недопустимое значение" после обновления платформы.
Ключевой момент в данной проблеме — это работа с объектом ФиксированныйМассив. Фиксированный массив является неизменяемым объектом. Это означает, что после его создания мы не можем добавлять в него новые элементы, удалять существующие или изменять их последовательность. Однако, в данном случае, ошибка возникает не при попытке непосредственного изменения элементов исходного ФиксированногоМассива, а на строке, где происходит переприсвоение переменной ПараметрыВыбора:
ПараметрыВыбора = Новый ФиксированныйМассив(МассивДляВнешнихОбработок);
Эта строка пытается создать совершенно новый ФиксированныйМассив из временного Массива под названием МассивДляВнешнихОбработок и затем присвоить ссылку на этот новый объект переменной ПараметрыВыбора. Сама по себе такая операция переприсвоения ссылки на новый объект для переменной-параметра не является нарушением неизменяемости исходного ФиксированногоМассива. Проблема кроется глубже — в содержимом, которое мы пытались поместить в новый ФиксированныйМассив.
Проанализируем строку, отвечающую за заполнение временного массива:
МассивДляВнешнихОбработок.Добавить(ПараметрВыбора.Значение);
Здесь и кроется основная причина ошибки. Входящий параметр ПараметрыВыбора, судя по всему, является коллекцией, содержащей объекты типа ПараметрВыбора. Объект ПараметрВыбора, как правило, имеет два важных свойства: Имя и Значение. Однако в цикле мы добавляли во временный МассивДляВнешнихОбработок только свойство Значение каждого элемента.
Таким образом, после завершения цикла, МассивДляВнешнихОбработок содержал не коллекцию объектов ПараметрВыбора, а коллекцию простых значений (например, строк, чисел или ссылок). Когда из этого временного массива затем создавался новый ФиксированныйМассив, он также содержал только эти простые значения.
Конечная точка назначения этого ФиксированногоМассива — это свойство Элементы.ВнешняяОбработка.ПараметрыВыбора. Вероятнее всего, это свойство ожидает на вход коллекцию, состоящую из объектов ПараметрВыбора (т.е. объектов, которые имеют как Имя, так и Значение), а не просто список значений. Попытка присвоить этому свойству ФиксированныйМассив, элементы которого не соответствуют ожидаемому типу (т.е. вместо объектов ПараметрВыбора в нем оказались просто значения), и приводила к ошибке "Недопустимое значение".
Ужесточение контроля типов в новых версиях платформы 1С (начиная с 8.3.20.1996) сделало такие несоответствия более явными и приводило к критическим ошибкам, тогда как в более ранних версиях они могли игнорироваться или вызывать менее заметные проблемы. Платформа теперь более строго проверяет, соответствует ли тип элементов коллекции тому, что ожидается в целевом свойстве или параметре.
Для решения возникшей проблемы нам необходимо обеспечить, чтобы новый ФиксированныйМассив, который мы создаем, содержал элементы правильного типа, соответствующие ожиданиям системы. Если исходная коллекция ПараметрыВыбора состоит из объектов типа ПараметрВыбора, то и фильтрованная коллекция должна сохранять эту структуру.
Разберем шаги, которые мы предпримем для исправления кода:
Массив (Новый Массив) для промежуточного хранения отфильтрованных элементов. Это необходимо, так как Массив, в отличие от ФиксированногоМассива, позволяет нам свободно добавлять и удалять элементы.
МассивДляВнешнихОбработок только свойство Значение каждого элемента, мы будем добавлять весь объект ПараметрВыбора целиком. Это гарантирует, что каждый элемент в нашем временном массиве будет иметь структуру ПараметрВыбора (свойства Имя и Значение), что соответствует ожидаемому типу данных.
ФиксированныйМассив. После того как временный МассивДляВнешнихОбработок будет правильно заполнен корректными объектами ПараметрВыбора, мы создадим из него новый ФиксированныйМассив, используя конструктор Новый ФиксированныйМассив(МассивДляВнешнихОбработок). Этот новый фиксированный массив будет полностью корректным по структуре и типу элементов.
ФиксированныйМассив переменной-параметру. Строка ПараметрыВыбора = Новый ФиксированныйМассив(МассивДляВнешнихОбработок); останется без изменений. Теперь она будет работать корректно, поскольку новый ФиксированныйМассив содержит ожидаемые типы данных, и платформа не будет считать его "Недопустимым значением" при последующей передаче.
Вот как выглядит исправленная процедура, основанная на решении, предложенном на форуме. Для модификации типового кода без снятия конфигурации с поддержки, мы используем механизм расширений и соответствующие директивы компиляции:
&ИзменениеИКонтроль("УдалитьПараметрыВыбораРасширений")
Процедура ИСП32_УдалитьПараметрыВыбораРасширений(ПараметрыВыбора)
Если ПараметрыВыбора.Количество > 0 Тогда
МассивДляВнешнихОбработок = Новый Массив;
СтрокаПоиска = НСтр("ru = ''");
Для каждого ПараметрВыбора Из ПараметрыВыбора Цикл
Если СтрНайти(ПараметрВыбора.Значение, СтрокаПоиска) = 0 Тогда
#Удаление
МассивДляВнешнихОбработок.Добавить(ПараметрВыбора.Значение);
#КонецУдаления
#Вставка
МассивДляВнешнихОбработок.Добавить(ПараметрВыбора);
#КонецВставки
КонецЕсли;
КонецЦикла;
ПараметрыВыбора = Новый ФиксированныйМассив(МассивДляВнешнихОбработок);
КонецЕсли;
КонецПроцедуры
Как мы видим в исправленном коде, единственное, но критически важное изменение произошло в строке добавления элемента во временный массив:
МассивДляВнешнихОбработок.Добавить(ПараметрВыбора);
Теперь мы добавляем весь объект ПараметрВыбора, а не только его свойство Значение. Это позволяет сохранить исходную структуру и тип элементов, что устраняет ошибку "Недопустимое значение" при создании нового ФиксированногоМассива и его последующем использовании.
Работа с ФиксированнымМассивом в 1С требует особого внимания из-за его неизменяемой природы. Всегда держите в уме следующие принципы и рекомендации:
ФиксированныйМассив нельзя изменить после создания. Если вам необходимо получить измененный набор элементов, вы всегда должны создавать новый ФиксированныйМассив.
Массив (или Соответствие, Структуру и т.д.), выполните необходимые манипуляции, а затем создайте новый ФиксированныйМассив из полученного результата.
ФиксированногоМассива из временной коллекции убедитесь, что элементы этой коллекции имеют тот тип и структуру, которые ожидаются в месте использования ФиксированногоМассива. Если ожидаются объекты определенного типа (например, ПараметрВыбора), то и в новый ФиксированныйМассив должны попасть именно эти объекты, а не только их отдельные свойства.
&ИзменениеИКонтроль, #Удаление, #КонецУдаления, #Вставка, #КонецВставки являются мощным инструментом для точечного изменения кода.
Таким образом, понимание принципов работы ФиксированногоМассива, а также строгое соблюдение типов данных и структуры элементов при его формировании, являются фундаментальными для предотвращения подобных ошибок и обеспечения стабильной работы ваших решений на платформе 1С:Предприятие.