Имя: Пароль:
1C
1С v8
ЗначениеЗаполнено() за и против
,
0 Adecvator
 
27.04.15
15:28
Хочу спросить, кто чем пользуется, что бы проверить заполнено ли значение. Я не заморачиваюсь и использую всегда ЗначениеЗаполнено(), вместо пустой ссылки и тому подобное.
110 фобка
 
29.04.15
09:38
А по сути ЗначениеЗаполнено() не работает с мутабельными значениями. Это единственное ограничение. В остальных случаях применимо
111 СвинТуз
 
29.04.15
09:46
я думал эта функция для составных типов данных ...

а оно воно че ?

Ссылка.Пустая()=ЗначениеЗаполнено() ...
112 фобка
 
29.04.15
09:51
(111) = Не значениезаполнено(ссылка)
113 СвинТуз
 
29.04.15
10:09
(112)
можно вообще круто ...

документ.дата='00010101' => НЕ ЗначениеЗаполнено(документ.дата)

и т.п.
на самом деле это стильно, и не напряжно
используешь одну универсальную функцию и думать не нужно
114 vvp91
 
29.04.15
10:43
Банальный тест на типовой демобазе в платформе 8.3.5.1517 дает такие результаты
ЗначениеЗаполнено: 3 650 400 из 3 796 416 за 58,64 сек.
Прямые сравнения: 3 650 400 из 3 796 416 за 145,844 сек.

Еще такой важный момент пропускают противники ЗначениеЗаполнено, что функция очень лаконична, а полноценную проверку на заполненность мало кто напишет.


//////////////////////////////////////////
ВЫБРАТЬ null КАК Тест
ПОМЕСТИТЬ ТТ
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ НЕОПРЕДЕЛЕНО
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ""
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "1"
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ К.Ссылка ИЗ Справочник.Контрагенты КАК К
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ Д.Ссылка ИЗ Документ.РеализацияТоваровУслуг КАК Д
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ЗНАЧЕНИЕ(Документ.РеализацияТоваровУслуг.ПустаяСсылка)
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(1, 1, 1)
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2015, 4, 29)
;
ВЫБРАТЬ
    ТТ.Тест
ИЗ
    ТТ КАК ТТ, ТТ КАК Т1, ТТ КАК Т2

//////////////////////////////////////////
Заполнено = 0;
Начало = ТекущаяУниверсальнаяДатаВМиллисекундах();
Для Каждого Выборка Из РезультатТаблица Цикл
    Если ЗначениеЗаполнено(Выборка.Тест) Тогда
        Заполнено = Заполнено + 1;
    КонецЕсли;
КонецЦикла;
Длительность = (ТекущаяУниверсальнаяДатаВМиллисекундах() - Начало) / 1000.;
Сообщить("ЗначениеЗаполнено: " + Заполнено + " из " + РезультатТаблица.Количество() + " за " + Длительность + " сек.");

// ЗначениеЗаполнено: 3 650 400 из 3 796 416 за 58,64 сек.

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

// Прямые сравнения: 3 650 400 из 3 796 416 за 145,844 сек.
115 ЧеловекДуши
 
29.04.15
10:58
(0) С датой не рискую, пишу "ЗначДаты <> Дата(1,1,1)" :)
А в остальном и ЗначениеЗаполнено() за глаза
116 Ненавижу 1С
 
гуру
29.04.15
11:00
Одна претензия к методу
Почему ЗначениеЗаполнено(Ложь)=Истина?
117 ViSo76
 
29.04.15
11:10
(116) Из хелпа

Возвращаемое значение:

Тип: Булево.
Для значений типа Булево всегда возвращается Истина.

Скорее всего булево есть булево и этим всё сказано.
118 СвинТуз
 
29.04.15
11:16
(116)
потому что ЛОЖЬ=0
119 Ненавижу 1С
 
гуру
29.04.15
11:19
(117) да читал я это, но по-моему это методолгически криво
для всех типов значение по-умолчанию дает Ложь, а для булева нет
(118)и?
120 СвинТуз
 
29.04.15
11:22
(119)
а 0 это пустое значение
Истина = число больше >0 любое

(114)
в таком контексте конечно
121 СвинТуз
 
29.04.15
11:23
(116)
хотя я опять путаю ...
)
122 фобка
 
29.04.15
11:40
(116) дык можно написать свою функцию которая будет давать ложь) ложь это тоже значение. Трехзначная логика, ведь может быть и неопределено/null
123 Ненавижу 1С
 
гуру
29.04.15
11:42
(122) не о том речь
124 rphosts
 
29.04.15
11:44
(108) к себе примените
125 фобка
 
29.04.15
11:45
(118) сам тип булево это истина или ложь, а в БД уже применима трехзначная логика
126 фобка
 
29.04.15
11:46
125 к (119)
127 Ненавижу 1С
 
гуру
29.04.15
11:46
(125) и чего? к чему ты это написал?
128 фобка
 
29.04.15
11:54
(127) к тому что кривизны не вижу
129 ViSo76
 
29.04.15
12:50
(124) У тебя в профиле картинка 1 степень за флуд. В твоём случае лучше жевать чем говорить.
130 ViSo76
 
29.04.15
13:07
(114) Скорость исполнения скорее всего указывает на то что в функции ЗначениеЗаполненно нет батареи case. Да и само предположение такое опускает разработчиков 1С ниже плинтуса.
131 rphosts
 
29.04.15
13:36
(129)во первых - это не твоё дело, а во вторых первого достаточно
132 фобка
 
29.04.15
13:48
(114) тест неполный) нужно еще 3 вариант - прямое сравнение данных одного типа (например, дата) с пустым значением для этого типа
133 Kyon8
 
29.04.15
13:55
(130) Как вариант - case на С++ на котором написана платформа гораздо быстрее case на 1С.
134 olegves
 
29.04.15
14:10
(116) например, для реквизита составного типа(число, булево, ссылка) для значения булева ЛОЖЬ тебе чего возвращать?
135 DEVIce
 
29.04.15
14:12
(11) Зато не надо греть голову типизацией. Я всегда юзаю именно ЗначениеЗаполнено(), не думаю что это как-то значительно влияет на производительность.
136 DEVIce
 
29.04.15
14:13
(23) Да ладно? Даже при проверке примитивных типов?
137 ViSo76
 
29.04.15
14:18
(133) Ещё один (131) при чём тут язык 1С?
138 боксер
 
29.04.15
14:24
провел свои тест. испытания. проверка в цикле. результаты:
1 000 000 раз ,если док.Пустая()4сек.
1 000 000 раз ,если значениезаполнено(док)5сек.
1 000 000 раз ,если док.Пустая()4сек.
1 000 000 раз ,если значениезаполнено(док)5сек.
ч.т.д.
139 боксер
 
29.04.15
14:26
это на ноуте.файловая.
проверьте на своем:
Процедура КнопкаВыполнитьНажатие(Кнопка)
    д=текущаядата();
    н=1000000;
    Если Флажок1 Тогда
        Для инд=1 по н Цикл
            Если док.Пустая() Тогда
            
            КонецЕсли;
        КонецЦикла;
        Сообщить(""+н+" раз ,если док.Пустая()"+(текущаядата()-д)+"сек.");
    ИНАЧЕ    
        Для инд=1 по н Цикл
            Если значениезаполнено(док) Тогда
            
            КонецЕсли;
        КонецЦикла;
        Сообщить(""+н+" раз ,если значениезаполнено(док)"+(текущаядата()-д)+"сек.");
    КонецЕсли;
КонецПроцедуры
140 ViSo76
 
29.04.15
14:33
(138) Я думаю что результат таков по тому что в 1-м случае сразу вызывается метод проверки на заполненности у объекта, а во втором идёт преобразование к базовому объекту и вызов того же самого метода ( механизм полиморфизма ) что требует несколько больших затрат.
141 боксер
 
29.04.15
14:35
естественно , универсальный метод более затратен
142 ViSo76
 
29.04.15
14:36
У тебя некорректный пример.
143 фобка
 
29.04.15
14:37
(138) прикольно, 1 сек разницы на 1млн записей
144 ViSo76
 
29.04.15
14:38
Это подтверждает что Архитектор 1С заслуживает своего титула Архитектор
145 ViSo76
 
29.04.15
14:39
Сама 1С написана в лучших традициях ООП
146 DEVIce
 
29.04.15
14:39
(141) Целая секунда разницы на миллионе итераций - существенная экономия, ага. :)
147 ViSo76
 
29.04.15
14:42
Чуваки выше пели по кучу case внутри функции ЗначениеЗаполненно. Если бы так писали такие программы как 1С то уже бы давно бы 1С развалился, так как поддерживать такой быдлокодинг было бы нереально.
148 DEVIce
 
29.04.15
14:51
(147) Ага, если там не case, то что? if? Думаешь перегрузка метода быстрее условия работает? Ой я сильно сомневаюсь.
149 DEVIce
 
29.04.15
14:53
Да и перегрузка она всяко чтобы вызвать нужную реализацию метода что-то сравнивает, т.е. таки case никуда не делся, просто на другом уровне работает, что в компиленном коде ни на что не влияет.
150 DEVIce
 
29.04.15
14:56
Что такое перегрузка метода? Это таблица вызовов, в которой записано соответствие сигнатуры с адресом вызова, т.е. таки чтобы вызвать нужную реализацию метода, надо сделать или case или полный перебор всех строк таблицы до попадания сигнатуры, что по сути тоже самое.
151 ViSo76
 
29.04.15
15:05
Никаких case и переборов нет в помине. При компиляции сразу подставляется смещение относительно таблицы берётся от туда адрес и происходит переход.
152 ViSo76
 
29.04.15
15:07
Базовый класс наверняка абстрактный был с абстактной функцией определения заполненности и типа которую в обязательном порядке потомки должны перегружать
153 rphosts
 
29.04.15
15:20
(137)чушь перестань нести!
154 rphosts
 
29.04.15
15:22
(133) причём тут язык? ЗначениеЗаполнено() выполняется не средствами языка 1С а готовым откомпилированным кодом.
155 DEVIce
 
29.04.15
15:25
(151) Каким образом берется? Раскрой нам секрет.
156 rphosts
 
29.04.15
15:26
Если-б мне нужно было-бы сделать быстрое определение заполненности то это реализовывалось-бы в 3 шага:
1.при старте конфигурации формировался массив пустых значений для каждого типа конфигурации.
2.при вызове сравнения по порядковому номеру типа выбиралось из массива соответствующее ему пустое значение.
3.сравнивался аргумент вызова Значение заполнено() с полученым на 2 шаге.
157 rphosts
 
29.04.15
15:26
(155) кста, если копнуть возможно пустое значение для каждого нового/изменённого типа создаётся при сохранении конфигурации и хранится в ней
158 DEVIce
 
29.04.15
15:28
(152) Ты гонишь. Какое нафиг смещение? Как узнать на какое из сто тыщ мильенов реализаций метода надо сместиться? Идет сравнение сигнатуры метода. Не думаешь же ты что таблица индексируется и юзается хэш? Вычисление хыша займет на несколько порядков больше времени, нежели тупой и примитивный case.
159 DEVIce
 
29.04.15
15:29
(157) Ага, особенно если вспомнить, что 1С - это интерпретатор.
160 rphosts
 
29.04.15
15:30
(159) это запрещает хранить?
161 DEVIce
 
29.04.15
15:30
(152) У тебя же образование программиста? Ты же понимаешь, что все эти перегрузки, виртуальные функции и прочее в итоге превращаются в машинный код, где это все реализуется нашим любимым case'ом?
162 DEVIce
 
29.04.15
15:32
(160) Для всех возможных случаев, методанных то может быть много разных? Можно, но тогда это будет работать на уровне интерпретатора 1С и ниже уже не опуститься.
163 rphosts
 
29.04.15
15:37
(162)спрошу по другому: структура ссылки не кодирует в нескольких разрядах тип верхнего уровня (Документ, справочник...), а в некотором количестве следующих на ним порядковый номер из конфигурации?
164 ViSo76
 
29.04.15
15:47
(158) Так хватит нести пургу объясняю:

Есть объект потомок у него есть таблица перегруженных методов эта таблица создаётся в каждом экземпляре объекта. В этой таблице жёстко прописано:

Начало таблицы:

Смещение 0 относительно таблицы:

1. функция проверки на пустое значение. занимает к примеру 4 байта

Смещение 4 относительно таблицы:

2. функция возврата типа объекта

Нужно вызвать метод проверки пустого значения

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

Call Object + Table + 1 * 4 ( Но Offset относительно функции вычисляется при  компиляции )
165 ViSo76
 
29.04.15
15:51
(164) Точнее Call Object + Table + 0 * 4. Никакого case и в помине нет я долго сидел на assebler такая команда есть только в высокоуровневых языках. CASE реализуется командами jp с условиями
166 Jokero
 
29.04.15
15:53
(11) Ну вот, моя жизнь теперь никогда не будет прежней(

Сам всегда использую ЗначениеЗаполнено() - думал это фича, оказывается это баг(
167 olegves
 
29.04.15
15:57
(156) а что твоя функция вернет для реквизита формы составного типа (например, документ.ссылка), где допустимые типы определяются при создании на сервере?
168 rphosts
 
29.04.15
16:03
(167) как конкретное значение может быть составного типа?
169 ViSo76
 
29.04.15
16:15
(168) Ты проверяешь реквизит формы к примеру который ещё не инициализированн
170 rphosts
 
29.04.15
16:18
(169) Если форма уже существует - её реквизиты уже инициализированы, по крайней мере в УФ.
171 ViSo76
 
29.04.15
16:18
(170) И составного типа которые ещё не заполнены?
172 rphosts
 
29.04.15
16:20
(171) Неопределено?
173 ViSo76
 
29.04.15
16:27
(172) Разуется но это не инициализация, а просто признак у объекта что он ещё не инициализировался
174 Ненавижу 1С
 
гуру
29.04.15
16:37
(173) стоять. Неопределено это значение вполне определенного типа (извините за каламбул, но это 1С) и этот тип - Неопределено
175 rphosts
 
29.04.15
16:43
(174) совершенно верно
176 pessok
 
29.04.15
17:13
дайте влезть уже, а то зачитался холивара. На определяемых типах уже тестили? :D
177 ViSo76
 
29.04.15
17:19
(174) Скорее всего Неопределено и есть базовый тип в иерархии объектов 1С.
178 ДенисЧ
 
29.04.15
17:20
(177) А NULL??
179 pessok
 
29.04.15
17:24
(178) *just for loolz* а NULL <> Неопределено?
/me подмигивает Ненавижу 1С
180 ViSo76
 
29.04.15
17:25
(178) NULL это опеределёный тип базы данных и Неопределено это тоже базовый тип
181 ДенисЧ
 
29.04.15
17:28
(179) NULL вообще ничему не равно...
182 pessok
 
29.04.15
17:28
расскажите уже про определяемые типы, тестить лениво
183 ViSo76
 
29.04.15
17:29
(181) NULL = NULL
184 pessok
 
29.04.15
17:29
(183) не хочу тебя расстраивать
185 ДенисЧ
 
29.04.15
17:30
(183) неа...
186 pessok
 
29.04.15
17:31
(185) однако я проверил... NULL = NULL... Истина, пля... 8.3.5.1443
187 pessok
 
29.04.15
17:34
+(186) а так Ложь...
    Запрос = Новый Запрос(
    "ВЫБРАТЬ
    |    ВЫБОР
    |        КОГДА Нуллы.Нулл1 = Нуллы.Нулл2
    |            ТОГДА ИСТИНА
    |        ИНАЧЕ ЛОЖЬ
    |    КОНЕЦ КАК Результат
    |ИЗ
    |    (ВЫБРАТЬ
    |        NULL КАК Нулл1,
    |        NULL КАК Нулл2) КАК Нуллы");
    
    Выборка = Запрос.Выполнить().Выбрать();
    Выборка.Следующий();
    Сообщить(Выборка.Результат);
188 ViSo76
 
29.04.15
17:45
(187) В базе данных null проверяется только функцией и всегда null = null даёт null и разумеется в case ( ВЫБОР ) будет false
189 ViSo76
 
29.04.15
18:51
Так же как true = null результат null и т.д. любое сравнение с null даст null в базе данных null это неинициализированое значение
190 rphosts
 
30.04.15
01:56
(0) какой наманый вброс получился... прям для пятницы которая неа этой неделе в четверг
191 Альбатрос
 
30.04.15
05:20
Ну чо там? жду продолжения, я уже вторую корзину попкорна взял
192 rphosts
 
30.04.15
06:40
(191) нужно было пиво брать и диван... сейчас мск проснётся и понеслась!
193 Ненавижу 1С
 
гуру
30.04.15
08:13
(181) не ври, в коде 1С (не запросах) верно написали NULL=NULL
отсюда вывод, что модель 1С крайне кривая, поведение в разных местах различно
а придумывая неопределено и пустые ссылки для записи в БД считаю порочной практикой от 1С!
194 pessok
 
30.04.15
10:13
(193) +
195 tznimble
 
30.04.15
12:31
1. В 1С (следующей технологии .net) простые типы - объекты (пример http://referencesource.microsoft.com/#mscorlib/system/int32.cs,225942ed7b7a3252)
2. Таблица виртуальных методов (а все перегружаемые - виртуальны) содержит ссылки на выполняющие функции и привязана к экземпляру объекта. Если в пределах одного объекта делается перегрузка по набору параметров или их типу - создаются разные виртуальные функции.
То есть, когда в коде мы встречаем выражение типа Object.VFunc адрес, по которому передаётся управление берется из массива виртуальных функций (что делается ОДНОЙ командой процессора на Inetl'ах).  
3. Пустые ссылки объектов БД в 1С выглядят как GUID состоящий из нулей, что легко проверяется БЕЗ дополнительного обращения к базе.
4. Тип Неопределено является-таки объектом
5. А вот состояние Empty в 1С не предусмотрено
6. ЗначениеЗаполнено не работает с мутабельными значениями именно из-за того, что само мутабельное значение ссылкой как бы не является (но мы-то знаем...)
196 Aceforg
 
30.04.15
12:51
(195) Так все таки ЗначениеЗаполнено сваливается в запрос?
Если нет, выполняется каскад "если иначе" или вызывается виртуальная функция?
197 tznimble
 
30.04.15
13:22
(196) ЗначениеЗаполнено (ValueIsFilled)
Возвращает Истину в случае, если значение отлично от значения данного типа по умолчанию, отличное от значения NULL, отличное от пустой ссылки, отличное от значения Неопределено. Для логических значений осуществляется проверка на значение NULL. Для строк осуществляется проверка на отсутствие не пробельных символов.

Параметром является СсылкаНаОбъект (ref).
При вызове ЗначениеЗаполнено:
1. Проверяется, что Ссылка не пустая и не Неопределено
2. Вызывается соответствующий метод переданного объекта (вычисляется адрес вызова addr [ref.VTable] + ValueIsFilled_offset и осуществляется переход по нему)

Наличие первого пункта объясняет почему Док.Пустая() работает несколько медленнее ;)
Отсутствие оно приводит к тому что в случае Док=Неопределено вместо ложь мы получаем ошибку
198 tznimble
 
30.04.15
13:27
(196) к (197) Док.Пустая() - несколько быстрее (sorry)
199 Aceforg
 
30.04.15
13:46
(196) Спасибо. Где можно получить информацию такого плана? На курсах подготовки к Эксперту? Форум этот читать?
200 ViSo76
 
30.04.15
13:53
(195) 1. На самом деле простые типы ( Byte, String и т.д. ) к примеру в C# остаются простыми типами. Объекты они только в IDE.
201 Goggy
 
30.04.15
13:54
Боже. На мисте и правда скучно становится раз такие темы набирают популярности...
202 tznimble
 
30.04.15
13:58
(200) Вам ссылка официальная из MSDN для чего приведена?
Вот после компиляции и оптимизации они станут простыми. И проверка их заполненности станет скорее всего инлайном и для int32 будет выполняться как mov eax,... // jnz <>
203 ViSo76
 
30.04.15
14:01
(202) Я про после компиляции и сказал
204 Ненавижу 1С
 
гуру
30.04.15
14:02
(195) >>А вот состояние Empty в 1С не предусмотрено

Да, необходимо ввести, а то их так мало


>>что делается ОДНОЙ командой процессора на Inetl'ах

Учитывая, что 1С генерит не машинный код, а интерпретатор
205 ViSo76
 
30.04.15
14:06
(204) Ты не в теме. Это разговор о том как внутри функционирует 1С. А не про то как 1С исполняет Р-код
206 tznimble
 
30.04.15
14:08
(204) Интерпретатор 1С просто переводит готовый байт код в вызовы процедур. Но он сам НЕ вычисляет ссылки и т.д.
Вызов ЗначениеЗаполнено (Объект) выполняется как:
1. По имени переменной определяется область памяти, где хранится значение - реальная ссылка на реальный объект (в смысле машинного кода)
2. Определяется и вызывается реальная процедура ValueIsFilled (Reference)
3. Далее работает исключительно готовый, заранее скомпилированный на Си код
207 TeMochkiN
 
30.04.15
14:40
(195) >> 3. Пустые ссылки объектов БД в 1С выглядят как GUID состоящий из нулей, что легко проверяется БЕЗ дополнительного обращения к базе.

Объект удалили без контроля ссылочной целостности. Ссылка на него висит в реквизите другого объекта. Что вернет значениезаполнено при проверке данного реквизита? Истина, потому что там гуид ссылки не с нулями?

или я чего-то не понял?
208 TeMochkiN
 
30.04.15
14:43
(207) ой, невнимательно я вдумался, тут же ничего не написано про само значениеЗаполено))
209 ViSo76
 
30.04.15
14:57
(207)  Функция ЗначениеЗаполнено вернёт истина так как битая ссылка не равна 16 байт нулей
Основная теорема систематики: Новые системы плодят новые проблемы.