Показать сообщение отдельно
Старый 20.12.2020, 22:08   #6  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
up-ну тему.

Стали причесывать код. Там где раньше все нормально было, на тернарных операторах стало выдавать "operand types are not compatible with the operator" или "Типы операндов не совместимы с оператором."

Достает.
Можно как-то это убрать ?

Погуглил
Преобразование System.String в str
https://community.dynamics.com/ax/f/...patible/577041
https://community2.dynamics-int.com/...tor-in-ax-2012
http://www.javaear.com/question/28894455.html

Ясности не добавило.

Мне кажется это явно какой-то баг компилятора.
Так как аналогичный код написаный через if и оператор присваивания работает хорошо и ругани нет.

Для примера вот такой код из реального проекта

X++:
public static boolean validateField_MRC(Common _record, FieldId _fieldId, boolean _ignoreDataSourceLevel = false)
{
    DictField       dictField;
    FormDataSource  fds;
    FormDataObject  fdo;
    str             testStr;
    container       con;
    
    boolean ret;
    ;

    dictField = new DictField(_record.TableId, _fieldId);

    fds = null; // не ругается
    
    fds = !_ignoreDataSourceLevel ? (SysDictClass::as(_record.dataSource(), classNum(FormObjectSet))) : null; // не ругается
    fds = !_ignoreDataSourceLevel ? (SysDictClass::as(_record.dataSource(), classNum(Object))) : null; // не ругается
    
    fds = !_ignoreDataSourceLevel ? _record.dataSource() : null; // ругается
    fdo = fds ? fds.object(_fieldId) : null;

    ret = !(dictField.mandatory() || (fdo && fdo.mandatory())) || validateFieldIsSet_MRC(_record, _fieldId);
    if (ret)
    {
        ret = fdo ? fdo.validate() : _record.validateField(_fieldId); // ругается - один boolean отличается от другого ?
        ret = fdo ? fdo.validate() : any2int(_record.validateField(_fieldId)); // не ругается
        ret = fdo ? fdo.validate() : any2enum(_record.validateField(_fieldId)); // не ругается
        
        ret = fdo.validate(); // не ругается
        ret = _record.validateField(_fieldId); // не ругается
    }

    testStr = conPeek(con, 1) ? conPeek(con, 2) : @""; // ругается
    testStr = conPeek(con, 2);  // не ругается
    testStr = @"";   // не ругается
    
    return ret;
}
1. Как можно это обойти ? Неужели везде дописывать any2XXX(..) ?
2. Какие идеи почему так сделано ?

Мне пока кажется что это из-за проблем с маршаллингом X++ <---> CIL

Самый простой способ, какой нашел - юзать any2XXX() функции - так читаемость кода страдает меньше всего. Либо переделывать на if else c явным присваиванием.
Для случая классов и таблиц можно написать в Global свои методы any2Object_MRC() и any2Common_MRC(). Можно также задействовать SysDictClass::as()

X++:
// см. также Global::asObject()
static public Object any2Object_MRC(anytype _parm)
{
    Object      ret;
    ;

    switch (typeOf(_parm))
    {
        case Types::Class:
            // info("         any2Object_MRC:Class");
            return _parm;
            // break;
            
        case 44: // typeOf(null)
            // info("         any2Object_MRC:null of Class");
            return _parm;
            // break;
            
        case Types::AnyType: // такое бывает когда дефолтное значение anyType приходит в CIL
            // info("         any2Object_MRC:anyType");
            return _parm;
            // break;
            
        default:
            // info("         any2Object_MRC:other");
    }

    return ret;
}
X++:
// см. также Global::asCommon() 
// и SysDictTable::as()
// 
static public Common any2Common_MRC(anyType _parm)
{
    ;

    return _parm;
}
но они нормально работают только для ненулевых ссылок. Особенно в CIL.

Последний раз редактировалось Logger; 20.12.2020 в 22:19.