AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 20.08.2004, 15:53   #1  
monk is offline
monk
Участник
 
67 / 12 (1) ++
Регистрация: 14.10.2002
Проверка на RecId
Привет.
Возник следующий вопрос:

Есть код:
Table1 table1 = Table1::find(_Key);

далее проверка, которую можно выполнить двумя способами
;
if (table1)
{
.....
}

и

if(table1.recId)
{
...
}

Является ли первый способ корректным?
Старый 20.08.2004, 16:09   #2  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
в первом, насколько я понимаю, способе происходит неявное преобразование типов.
при преобразовании Common -> Int, Аксапта самостоятельно подставляет recID.

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

(Рекомендацию видел где-то в презентациях, где точно уже не помню)
Старый 20.08.2004, 16:32   #3  
Maxim Gorbunov is offline
Maxim Gorbunov
Administrator
Соотечественники
Лучший по профессии 2009
 
2,483 / 645 (26) +++++++
Регистрация: 27.11.2001
Адрес: Dubai, UAE
Только не Common в int, а Common в boolean.

Во втором случае тоже преобразовние: int в boolean

Чтобы быть уверенным на 110%, пишите
if (table1.RecId != 0) {
...
}
__________________
Not registered yet? Register here!
Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me
Старый 20.08.2004, 16:51   #4  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Изначально опубликовано Maxim Gorbunov
Только не Common в int, а Common в boolean.
Да, согласен. Спасибо.
Старый 22.08.2004, 06:32   #5  
Alks is offline
Alks
Участник
 
336 / 41 (2) +++
Регистрация: 23.07.2004
Адрес: г. Новокузнецк
Категорически не соглашусь с "мэтрами" :

1. Правила по преобразованию примитивных типов к логическому выражению в условиях, которые X++ унаследовал от C/C++ никто и никогда отменять не будет. Чётко и ясно сказано что нулевое значение аргумента воспринимается компилятором как false, а ненулевое - true, сомневаться в этом - значит проявлять незнание языка и плодить излишне перегруженный конструкциями код.
if ( a )... всегда было и будет предпочтительнее чем if ( a != 0 ) так же как и
if ( !( a < b ) ) выглядит запутаннее и непонятнее, чем if ( a >= b )
(кстати в практике программирования на 1С встречал следующий код:
Если НЕ(ОсталосьСписать>0) Тогда
Прервать;
КонецЕсли;
долго смеялся )

2. То же самое касается и преобразования Common в boolean.
if ( tbl ) выглядит гораздо проще и интуитивно понятнее чем if ( tbl.RecId )
Чем обоснованы рекомендации предпочитать tbl.RecId мне непонятно, ведь если когда нибудь правило преобразования Common в boolean хотя бы слегка изменят, половина кода аксапты станет неработоспособной, посему его никогда не изменят.
В общем я предпочитаю if ( table1 )

Хотя в принципе всё это вопрос вкуса и относится к той же теме что и вопрос о том звёздочками или плюсиками лучше помечать блоки комментариев в коде.
Старый 23.08.2004, 09:52   #6  
Wamr is offline
Wamr
----------------
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
 
1,737 / 858 (32) +++++++
Регистрация: 15.01.2002
Адрес: Москва
Записей в блоге: 7
Проверка If(table) более интеллектуальна, чем проверка If(table.RecID).
Например, после агрегации и ограничения списка выбираемых полей возможна ситуация, когда RecId = 0, но If(table) = true

Для проверки после find, действительно, нет разницы как проверять наличие результата.
Старый 23.08.2004, 10:14   #7  
Ser is offline
Ser
NavAx
 
99 / 14 (1) ++
Регистрация: 04.03.2002
Адрес: Москва
уже довольно давно правил такой код на форме накладных:
PHP код:
FactureEditLinesCust_RU.enabled(CustInvoiceJour.RecId);
FactureCust_RU.enabled(CustInvoiceJour.RecId); 
в некоторых случаях перечисленные элементы ну никах не желали активироваться.

только исправление на:
PHP код:
FactureEditLinesCust_RU.enabled((CustInvoiceJour.RecId true false));
FactureCust_RU.enabled((CustInvoiceJour.RecId true false)); 
ситуацию разрешило.

Это конечно же не конструкция if, но все равно аргумент должен приводиться к логическому типу
__________________
Чудес не бывает (c), истина где-то рядом (c)...
Старый 23.08.2004, 10:18   #8  
bucken is offline
bucken
Участник
Аватар для bucken
 
259 / 12 (1) ++
Регистрация: 04.09.2003
Адрес: Москва
флуд
Цитата:
Чётко и ясно сказано что нулевое значение аргумента воспринимается компилятором как false, а ненулевое - true, сомневаться в этом - значит проявлять незнание языка и плодить излишне перегруженный конструкциями код.
Вот тоже решил чуть усомниться ...
Какой компилятор может быть во время выполения?
__________________
Уточните значение слов и вы избавите человечество от половины его заблуждений. (Рене Декарт) / Axapta 2.5
Старый 23.08.2004, 12:31   #9  
Alks is offline
Alks
Участник
 
336 / 41 (2) +++
Регистрация: 23.07.2004
Адрес: г. Новокузнецк
Цитата:
...
FactureEditLinesCust_RU.enabled(CustInvoiceJour.RecId);
...
только исправление на:
...
FactureEditLinesCust_RU.enabled((CustInvoiceJour.RecId ? true : false));
...
ситуацию разрешило.
...
аргумент должен приводиться к логическому типу
Честно говоря когда понял до конца что тут написано - ржал как конь!

Если бы ты написал
CustInvoiceJour.RecId != 0
то фраза "аргумент должен приводиться к логическому типу" имела бы смысл, а так просто очевидно что это либо очередной и довольно серьезный и тонкий глюк аксапты, либо пятна на солнце.
CustInvoiceJour.RecId ? true : false - это масло масляное в использованном контексте...

Было бы интересно проверить эту "фичу" в своём проекте.

P.S.

И в свете того что я говорил в первом своём посте тут:

А FactureEditLinesCust_RU.enabled( CustInvoiceJour ) не пробовали?
Старый 23.08.2004, 12:41   #10  
Alks is offline
Alks
Участник
 
336 / 41 (2) +++
Регистрация: 23.07.2004
Адрес: г. Новокузнецк
Re: флуд
Цитата:
Вот тоже решил чуть усомниться ...
Какой компилятор может быть во время выполения?
Усомняться не стоит - просто читать внимательнее надо - я же говорил про:
Цитата:
...которые X++ унаследовал от C/C++ никто и никогда отменять не будет.
По инерции думал про C++, не спорю что X++ не C++, но смысл сказанного от этого не становится непонятнее.

Да и вообще если язык программирования не может справится с чётко оговоренным преобразованием числа в булевский тип - то какая разница компилятор он или интерпретатор?
Старый 23.08.2004, 15:36   #11  
Ser is offline
Ser
NavAx
 
99 / 14 (1) ++
Регистрация: 04.03.2002
Адрес: Москва
Фраза "аргумент должен приводиться к логическому типу" относится к правилу преобразования аргумента системой, но не к указанному варианту решения.

Я был тоже немало удивлен, но при этом сохранил человеческие повадки
__________________
Чудес не бывает (c), истина где-то рядом (c)...
Старый 23.08.2004, 16:09   #12  
db is offline
db
Роман Долгополов (RDOL)
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
 
393 / 692 (24) +++++++
Регистрация: 01.04.2004
Адрес: Москва
Цитата:
Изначально опубликовано Alks
сомневаться в этом - значит проявлять незнание языка и плодить излишне перегруженный конструкциями код ......

долго смеялся )

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

PHP код:
static void Job9(Args _args)
{
    
int             i = -1;
    
boolean         b;
    
InventTable     inventTable;


    while (
!= -1000)
    {
        
i;
        if (! 
b)
        {
            print 
i" "b" !!!";
        }
        
i--;
    }

    
inventTable.(fieldnum(CommonRecId)) = -512;

    if (
inventTable)
    {
        print 
"ok";
    }
    else
    {
        print 
"!!!";
    }

    if (
inventTable.RecId && 100 4)
    {
        print 
"ok";
    }
    else
    {
        print 
"!!!";
    }

    
inventTable && 100 4;

    if (
b)
    {
        print 
"ok";
    }
    else
    {
        print 
"!!!";
    }


    
inventTable.RecId;

    if (
b)
    {
        print 
"ok";
    }
    else
    {
        print 
"!!!";
    }

    
pause;


Axapta 3.0 SP3. То же самое в 2.5 и 2.1 Этому приколу уже лет 5.
Ну неправильно работет преобразование типов при присвоении int к boolean. В остальном все ок

Так что сомневаться бывает очень полезно
Старый 23.08.2004, 16:49   #13  
George Nordic is offline
George Nordic
Модератор
Аватар для George Nordic
Злыдни
 
4,479 / 1250 (50) ++++++++
Регистрация: 17.12.2003
Адрес: Moscow
Записей в блоге: 9
Хм.. и best practise молчит насчет сравнения или проверки на наличие записи по RecId... Единственное, что нашлось:
PHP код:
//Example
static boolean exist(CustGroupId custGroupId)
{
   return  custGroupId && (select firstonly recId from custGroup
                           index hint GroupIdx
                           where custGroup
.custGroup     == custGroupId).recId != 0;

Так что будем юзать RecId != 0

to db: спасибо за инфу - есть над чем задуматься...
Каждое Ваше сообщение - либо дельный совет, либо куча загадок

С Уважением,
Георгий
Старый 24.08.2004, 05:53   #14  
Alks is offline
Alks
Участник
 
336 / 41 (2) +++
Регистрация: 23.07.2004
Адрес: г. Новокузнецк
Цитата:
Изначально опубликовано db


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

PHP код:
static void Job9(Args _args)
{
    
int             i = -1;
    
boolean         b;
    while (
!= -1000)
    {
        
i;
        if (! 
b)
        {
            print 
i" "b" !!!";
        }
        
i--;
    }

Так что сомневаться бывает очень полезно
Да у меня просто волосы дыбом встали! И ведь по результатам видно что происходит какая то хрень с преобразованием отрицательных чисел кратных 256 - такое ощущение что для них перед преобразованием в boolean сперва идет преобразование в однобайтовое число. Хотел бы я узнать каким алгоритмом пользуются создатели X++ при этом преобразовании что возникает такой нехарактерный глюк. По хорошему a == true на низком уровне должно преобразовываться в a != 0, а a == false в a == 0. Как тут можно допустить исключительные ситуации с отрицательными числами ума просто не приложу!

Однако, я всё таки сейчас поулыбаюсь бледной улыбкаой, сразу после предыдущего попробуйте следующий джобик:

PHP код:
static void Job9(Args _args)
{
    
int             i = -1;
    
boolean         b;
    while (
!= -1000)
    {
        
i;
        if (! 
i)
        {
            print 
i" "b" !!!";
        }
        
i--;
    }
    
pause;



так что if ( tbl ) вполне корректно.

В подтверждение этому обратите внимание на то что участок кода:

Цитата:
inventTable.(fieldnum(Common, RecId)) = -512;

if (inventTable)
{
print "ok";
}
else
{
print "!!!";
}

if (inventTable.RecId && 100 > 4)
{
print "ok";
}
else
{
print "!!!";
}

b = inventTable && 100 > 4;

if (b)
{
print "ok";
}
else
{
print "!!!";
}
Работает тоже совершенно корректно (просто inventTable && 100 > 4 трактуется по приоритету операций как (inventTable && (100 > 4)) это хорошо видно если начать задавать скобки явно), очевидно что проблемы начинаются когда X++ вынужден сохранять результат конвертации int->boolean в явно заданную переменную (возможно так же что и как параметр ф-ии тоже). Спасибо конечно за предупреждение - теперь буду проявлять осторожность при передаче чисел как параметров в ф-ии предполагающие boolean аргумент, но глядя на то сколько сравнений вида if ( tbl ) сидит в недрах sys слоя Аксапты я свою привычку менять не буду.
Старый 24.08.2004, 06:19   #15  
Alks is offline
Alks
Участник
 
336 / 41 (2) +++
Регистрация: 23.07.2004
Адрес: г. Новокузнецк
Цитата:
Изначально опубликовано Ser
Фраза "аргумент должен приводиться к логическому типу" относится к правилу преобразования аргумента системой, но не к указанному варианту решения.

Я был тоже немало удивлен, но при этом сохранил человеческие повадки
Извиняюсь если был груб, это неспециально. Замечу что я не обвинял вас и не сомневался в том что такого не может быть - было просто действительно смешно видеть такие ляпы в X++.

После постинга db рассеивается эта страшная тайна - передача параметра в ф-ю видимо испытывает те же трудности с конвертацией int->boolean что и явное присваивание переменной...
Старый 24.08.2004, 11:14   #16  
Alks is offline
Alks
Участник
 
336 / 41 (2) +++
Регистрация: 23.07.2004
Адрес: г. Новокузнецк
Вот еще некоторые любопытные факты из жизни конвертации чисел в boolean, немножко проливающие свет на то что находится под капотом сего глюка:

PHP код:
static void Job4(Args _args)
{
    
boolean b;
    
real x;
    
int ij;
    ;
    
// Финт ушами №1, крест на явной конвертации real->boolean
    // хотя в language guide написано что всё должно быть пучком
    
0.7;
    
x;
    if ( 
info"TRUE" ); else info"FALSE" );
    if ( 
info"TRUE" ); else info"FALSE" );
    
    
// Финт ушами №2, принуждение к неявной конвертации спасает дело даже
    // если целью является явная ( a && true = a )
    
= -512;
    if ( 
info"TRUE" ); else info"FALSE" );
    
= -512 && true;
    if ( 
info"TRUE" ); else info"FALSE" );

    
// Финт ушами №3, немного проясняющий странность поведения явной конвертации 
    // чисел в boolean. boolean на самом деле оказывается байтом в котором
    // дамгардовцы пытаются сохранить нижние 8 бит исходного числа, что у них
    // плохо получается если это число - отрицательное
    
for ( 250<= 260i++ )
    {
        
i;
        
b;
        
infoint2str) + "->" + (b?"true":"false") + "->" int2str) );
    }
    for ( 
= -250>= -260i-- )
    {
        
i;
        
b;
        
infoint2str) + "->" + (b?"true":"false") + "->" int2str) );
    }

И всё становится ясно!

ВИДИМО где то в недрах интерпретатора Axapta присваивание переменной булевского типа использует следующий алгоритм конвертации (записано на языке C):

byte int2bool( int i )
{
return i > 255 ? 255 : i;
}

По вине разработчиков случай на i < 0 никак не обрабатывается, что приводит к урезанию ответа до последнего байта в этом случае и как следствие некорректному результату при i < 0 и кратных 256.
Старый 24.08.2004, 12:00   #17  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
думаю, что все проще.
при присваивании булеву значению берется только младший байт

т.е. b = i выполняется как b = lowbyte(i)
Старый 24.08.2004, 12:22   #18  
Alks is offline
Alks
Участник
 
336 / 41 (2) +++
Регистрация: 23.07.2004
Адрес: г. Новокузнецк
Цитата:
Изначально опубликовано mazzy
думаю, что все проще.
при присваивании булеву значению берется только младший байт

т.е. b = i выполняется как b = lowbyte(i)
Нет. Выполните Job из моего последнего сообщения и поймете что всё обстоит именно так как я в нём написал, а именно: b = ( i > 255 ) ? 255 : lowbyte( i );

Преобразование real->boolean происходит по видимому еще хуже - сперва происходит преобразование real -> int с потерей дробной части (!!!) и только потом уже (по всё той же корявой схеме) из int -> boolean. Тихий ужас.
Спасает только то что эти корявости имеют место быть только при присвоении к булевским переменным/параметрам ф-й, подвыражения в выражениях же вычисляются правильно.
Старый 24.08.2004, 14:52   #19  
db is offline
db
Роман Долгополов (RDOL)
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
 
393 / 692 (24) +++++++
Регистрация: 01.04.2004
Адрес: Москва
Похоже я всех малость напугал, уж извините, больше не буду

Еще немножечко информации. Почти всю ее предыдущие авторы добыли методом тыка, просто подитожу то, что добыл когда то методом инструмента, против которого нет приема

Во первых аксаптовский интерпретатор не имеет типа boolean, там есть только enum,
который по совместительству используется как boolean

Преобразование int->enum
если int>255, то enum = 255, иначе enum=(BYTE)int
соответсвенно не прокатывают все отрицательные числа, кратные -256

Преобразование dbl->int
int=откинуть дробную часть(dbl)

Преобразование dbl->enum
int=откинуть дробную часть(dbl)
enum=(BYTE)int
соответственно не прокатывают все числа с откинутой дробной частью кратные как -256, так и +256

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

В общем, наслаждайтесь. Жизнь полна неожиданностей, тем она и прекрасна
Старый 24.08.2004, 15:28   #20  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Изначально опубликовано db
Похоже я всех малость напугал, уж извините, больше не буду
Нет, уж!
Огромное спасибо за вопросы!

Побольше бы таких неожиданных и интересных.
Теги
recid, баг, ошибка, ax3.0

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
if (record) vs if (record.RecId) kashperuk DAX: Программирование 18 27.11.2008 18:53
Как сформировать RecId Arahnid DAX: Программирование 18 14.07.2008 15:02
поля, содержащие RecId somebody DAX: Программирование 15 16.05.2008 17:50
aEremenko: Дефрагментация RecID Blog bot DAX Blogs 2 06.03.2007 22:25
Два RecId у одной записи таблицы sparur DAX: Программирование 33 18.12.2006 15:56

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 23:16.