Поделиться через


Операторы X++

Замечание

Группы интересов сообщества теперь переехали из Yammer в Microsoft Viva Engage. Чтобы присоединиться к сообществу Viva Engage и принять участие в последних обсуждениях, заполните форму " Запрос доступа к финансам и операциям Viva Engage Community " и выберите сообщество, к которому вы хотите присоединиться.

В этой статье описываются операторы, поддерживаемые в X++.

операторы присваивания

Назначение изменяет значение переменной или поля. В следующей таблице показаны операторы назначения X++. Нет разницы между префиксом и операторами постфикса.

Operator Description
= Назначьте выражение справа от знака равенства переменной слева.
+= Назначьте текущее значение переменной плюс выражение справа на переменную слева.
++ Увеличьте переменную на 1.
-= Назначьте текущее значение переменной минус выражение справа на переменную слева.
-- Уменьшение переменной на 1.

Примеры кода для операторов назначения

// An example of assignment operators and their output. 
static void Example1()
{
    int i = 1;
    // Using the = operator. i is assigned the value of i, plus 1. i = 2.
    i = i + 1;
    info(strFmt("Example 1: The result is "), i); // The result is 2.
}

static void Example2()
{
    int i = 1;
    // Using the += operator. i is assigned the value of i, plus 1. 
    // i = 2 (i = i + 1).
    i += 1;
    info(strFmt("Example 2: The result is "), i); // The result is 2. 
}

static void Example3()
{
    int i = 1;
    // Using the ++ operator. i is incremented by 1, and then 
    // by 1 again in the second statement. The final value of i is 3.
    i++;
    ++i;
    info(strFmt("Example 3: The result is "), i); // The result is 3. 
}

static void Example4()
{
    int i = 1;
    // Using the -= operator. i is assigned the value of i minus 1. 
    // i = 0 (i = i - 1).
    i -= 1;
    info(strFmt("Example 4: The result is "), i); // The result is 0. 
}

static void Example5()
{
    int i = 1;
    // Using the -- operator. i is decremented by 1, and then by 
    // 1 again in the second statement. The final value of i is -1.
    i--;
    --i;
    info(strFmt("Example 5: The result is "), i); // The result is -1. 
}

Арифметические операторы

Для выполнения числовых вычислений используются арифметические операторы. Большинство операторов являются двоичными и принимают два операнда. Однако оператор not (~) является унарным и принимает только один операнд. Синтаксис для двоичных операторов: expression1ArithmeticOperatorexpression2 Синтаксис для унарных операторов: ArithmeticOperatorexpression1

Operator Description
<< Оператор сдвигов влево выполняет выражение2 влево (умножение на 2) в выражении1.
>> Оператор сдвигов вправо выполняет выражение2 вправо (деление на 2) для выражения1.
* Оператор умножения умножает выражение1 на выражение2.
/ Оператор деления делит выражение1 на выражение2.
DIV Оператор целочисленного деления выполняет целочисленное деление выражения1 по выражению2.
MOD Оператор целочисленной оставшейся части возвращает оставшуюся часть целочисленного деления выражения1 по выражению2.
~ Оператор not , или унарный оператор, выполняет двоичную не операцию.
& Двоичный оператор AND выполняет двоичную операцию с выражением1 и выражением2.
^ Двоичный оператор XOR выполняет двоичную операцию XOR для выражения1 и expression2.
| Двоичный оператор OR выполняет двоичную или операцию с выражением1 и выражением2.
+ Оператор plus добавляет выражение1 в expression2.
- Оператор минус вычитает выражение2 из expression1.
? Оператор ternary принимает три выражения: expression1 ? expression2 : expression3. Если выражение1 имеет значение true, возвращается выражение 2 . В противном случае возвращается выражение3 .

Примеры кода для арифметических операторов

int a = 1 << 4;      // Perform four left shifts on 1 (1*2*2*2*2). a=16.
int b = 16 >> 4;     // Perform four right shifts on 16 (16/2/2/2/2). b=1.
int c = 4 * 5;       // Multiply 4 by 5. c=20.
int d = 20 / 5;      // Divide 20 by 5. d=4.
int e = 100 div 21;  // Return the integer division of 100 by 21. e=4 (4*21 = 84, remainder 16).
int f = 100 mod 21;  // Return the remainder of the integer division of 100 by 21. f=16.
int g = ~1;          // Binary negate 1 (all bits are reversed). g=-2.
int h = 1 & 3;       // Binary AND. Return the bits that are in common in the two integers. h=1.
int i = 1 | 3;       // Binary OR. Return the bits that are set in either 1 or 3. i=3.
int j = 1 ^ 3;       // Binary XOR. Return the bits that are set in 1 and NOT set in 3, and vice versa. j=2.
int k = 1 + 3;       // Add 1 and 3. k=4.
int l = 3 - 1;       // Subtract 1 from 3. l=2.
int m = (400 > 4) ? 1 : 5;  // If 400>4, 1 is returned. Otherwise, 5 is returned. Because 400>4, 1 is returned. m=1.

Операторы выражений

as Операторы is выражений управляют назначениями нижней рассылки. Назначения даукаста включают наследование классов или таблиц. Операторы назначения, которые неявно переадресовываются, могут привести к ошибкам, которые трудно прогнозировать и диагностировать. Ключевое as слово можно использовать для явной рассылки. Ключевое is слово можно использовать для проверки того, действительна ли подкачка во время выполнения.

Ключевое слово as

Используйте ключевое as слово для назначений, которые переадресуют из переменной базового класса в производную переменную класса. Ключевое as слово сообщает другим программистам и компилятору, что вы считаете, что ниспадающая рассылка будет допустимой во время выполнения.

  • Компилятор сообщает об ошибке для инструкций назначения внизу, которые не имеют ключевого as слова.
  • Во время выполнения ключевое слово приводит к тому, as что оператор назначения нижней рассылки назначается null , если даункаст недействителен.
  • Это is ключевое слово часто используется для безопасного проверки того, будет ли работать ключевое as слово.

Пример кода для ключевого слова в качестве ключевого слова

В следующем примере кода класс DerivedClass расширяет класс BaseClass . Пример кода содержит два допустимых назначения между его базовыми и производными переменными. Для назначения upcast для basec не требуется as ключевое слово, но назначение производной рассылки требует ключевого as слова. Следующий код компилируется и выполняется без ошибок.

static void AsKeywordExample()
{
    // DerivedClass extends BaseClass.
    BaseClass basec;
    DerivedClass derivedc;
    // BottomClass extends DerivedClass.
    BottomClass bottomc;
    derivedc = new DerivedClass();
    // AS is not required for an upcast assignment like this.
    basec = derivedc;
    // AS is required for a downcast assignment like this.
    derivedc = basec as DerivedClass;
    bottomc = new BottomClass();
    // AS causes this invalid downcast to assign null.
    bottomc = basec as DerivedClass;
}

Ключевое слово

Ключевое is слово проверяет, является ли объект подтипом указанного класса. is Выражение возвращает значение true, если объект является подтипом класса, или если объект имеет тот же тип, что и класс. Компилятор сообщает об ошибке, если is выражение ключевого слова сравнивает два типа, но ни один тип не является подтипом другого, и они не совпадают с одинаковым типом. Компилятор сообщает аналогичную ошибку для любого обычного оператора присваивания между двумя типами, где ни один тип не является подтипом другого, и они не имеют одного типа. Во время выполнения тип переменной, ссылающейся на базовый объект, не имеет значения ключевому слову is . Ключевое is слово приводит к проверке объекта, на который ссылается переменная, а не объявленный тип переменной, ссылающейся на объект.

Примеры кода для ключевого слова

В следующих примерах кода показаны условия, которые определяют, возвращается ли is выражение true или false. Примеры кода зависят от того, что класс Form и класс Query расширяют класс TreeNode .

// The compiler issues an error for the following code. 
// The compiler ascertains that the Form class and the Query class are not 
// part of the same inheritance hierarchy. Both the Form class and the Query class
// extend the TreeNode class, but neither Form nor Query is a subtype of the other.
Form myForm = new Form();
info(strFmt("%1", (myForm is Query)));

// The Infolog displays 0 during run time, where 0 means false. No supertype 
// object can be considered to also be of its subtype class.
TreeNode myTreeNode = new TreeNode();
info(strFmt("%1", (myTreeNode is Form)));

// The Infolog displays 0 during run time, where 0 means false. A null 
// reference causes the is expression to return false.
Form myForm;
info(strFmt("%1", (myForm is Form)));

// The Infolog displays 1 during run time, where 1 means true. 
// An object is an instance of its own class type.
Form myForm = new Form();
info(strFmt("%1", (myForm is Form)));

// The Infolog displays 1 during run time, where 1 means true. 
// Every subtype is also of its supertype.
Form myForm = new Form();
info(strFmt("%1", (myForm is TreeNode)));

// The Infolog displays 1 during run time, where 1 means true. 
// The type of the underlying object matters in the is expression,
// not the type of the variable that references the object.
Form myForm = new Form();
TreeNode myTreeNode;
myTreeNode = myForm; // Upcast.
info(strFmt("%1", (myTreeNode is Form)));

Пример кода для ключевых слов и ключевых слов

В следующем примере кода содержится типичное использование ключевого is слова. Ключевое as слово используется после проверки успешности ключевого isas слова. В этом примере isas ключевые слова являются прописными, чтобы сделать их более видимыми.

static void IsKeywordExample() 
{
    DerivedClass derivedc;
    BaseClass basec;
    basec = new DerivedClass();  // An upcast.
    if (basec IS DerivedClass)
    {
        info("Test 1: (basec IS DerivedClass) is true. Good.");
        derivedc = basec AS DerivedClass;
    }
    basec = new BaseClass();
    if (!(basec IS DerivedClass))
    {
        info("Test 2: !(basec IS DerivedClass) is true. Good.");
    }
}

//Output to the Infolog
Test 1: (basec IS DerivedClass) is true. Good.
Test 2: (!(basec IS DerivedClass)) is true. Good.

Класс object в качестве специального регистра

Класс Object может отображаться как особый случай в функциональных возможностях наследования. Компилятор пропускает проверку типа назначений переменным и из переменных, объявленных как объект типа. Некоторые классы наследуются от класса Object , некоторые классы наследуются от другого класса, а некоторые классы не наследуются от любого класса. Несмотря на то, что класс Dialog не наследует от любого класса, инструкции назначения и вызова в следующем примере кода работают. Однако если назначение bank4 = dlog3;не выполнено, он завершится ошибкой во время компиляции, так как классы Bank и Dialog не имеют отношения наследования друг к другу. Компилятор выполняет только одну небольшую проверку назначений переменной, объявленной классом Object . Компилятор проверяет, является ли элемент, назначенный переменной Object , экземпляром класса. Компилятор не позволяет назначить экземпляр буфера таблицы переменной Object . Кроме того, компилятор не разрешает примитивным типам данных, таким как int или str, назначаться переменной Object .

static void ObjectExample()
{
    Bank bank4;
    Object obj2;
    Dialog dlog3 = new Dialog("Test 4.");
    obj2 = dlog3;  // The assignment does work.
    obj2.run(false);  // The call causes the dialog to appear.
    info("Test 4a is finished.");
}

Tables

Все таблицы наследуются непосредственно из общей системной таблицы, если они явно не наследуются от другой таблицы. Не удается создать экземпляр общей таблицы. Он не существует в базовой физической базе данных. Общая таблица наследует от класса xRecord , но особым образом, который не подходит для ключевого is слова или ключевого as слова. as Если ключевое слово используется для выполнения недопустимой рассылки между таблицами, целевая переменная ссылается на неиспользуемую сущность без значения NULL. Любая попытка отмены ссылки на целевую переменную приведет к ошибке, которая останавливает программу.

Ключевые слова и расширенные типы данных

Каждый расширенный тип данных имеет свойство Extendeds . Стиль наследования, для элементов управления этим свойством отличается от стиля наследования, для которых isas предназначены ключевые слова.

Реляционные операторы

В следующей таблице перечислены реляционные операторы, которые можно использовать в X++. Большинство операторов являются двоичными и принимают два операнда. Однако оператор not (!) является унарным и принимает только один операнд. Синтаксис для двоичных операторов: expression1relationalOperatorexpression2 Синтаксис для унарных операторов: реляционное выражениеOperator1

Operator Description
like Подобный реляционный оператор возвращает значение true, если выражение1 похоже на выражение2.
== Оператор равной реляционной связи возвращает значение true , если оба выражения равны.
>= Больше или равно реляционному оператору возвращает значение true , если выражение1 больше или равно выражению2.
<= Меньше или равно реляционному оператору возвращает значение true , если выражение1 меньше или равно выражению2.
> Больше, чем реляционный оператор, возвращает значение true , если выражение1 больше выражения2.
< Меньше, чем реляционный оператор, возвращает значение true, если выражение1 меньше выражения2.
!= Не равный реляционный оператор возвращает значение true , если выражение1 отличается от (то есть, если оно не равно) expression2.
&& Оператор и реляционный оператор возвращает значение true, если выражение1 и expression2 являются истинными.
|| Оператор или реляционный оператор возвращает значение true, если выражение1 или выражение2 имеет значение true, или если оба имеют значение true.
! Оператор не или унарный реляционный оператор отрицает выражение. Возвращает значение true , если выражение имеет значение false и false , если выражение имеет значение true.

Оператор like

Оператор like может использовать * в качестве подстановочного знака для нуля или нескольких символов, а ? также в качестве подстановочного знака для одного символа. Максимальная длина операнда составляет 1000 символов. Оператор like оценивается базовым SQL, поэтому результат может отличаться в разных установках. Если выражения, которые вы сравниваете, содержат путь к файлу, необходимо включить четыре обратных косых фрагмента между каждым элементом, как показано в следующем примере.

select * from xRefpaths
where xRefPaths.Path like "\\\\Classes\\\\AddressSelectForm"

Оператор equal (==)

При использовании оператора равенства (==) для сравнения объектов сравниваются ссылки на объекты, а не сами объекты. Это может привести к проблемам, если сравнить два объекта, один из которых находится на сервере, а другой — на клиенте. В этих случаях следует использовать метод равенства в классе Object . Этот метод можно переопределить, чтобы указать, что означает для двух объектов, равных. Если вы не переопределяете метод равенства , сравнение идентично сравнению, которое выполняется оператором равенства (==).

Примеры кода для реляционных операторов

"Jones" like "Jo?es"  // Returns true, because the ? is equal to any single character.
"Fabrikam, Inc." like "Fa*"  // Returns true, because the * is equal to zero or more characters.
(( 42 * 2) == 84)  // Returns true, because 42*2 is equal to 84.
today() >= 1\1\1980  // Returns true, because today is later than January 1, 1980.
((11 div 10) >= 1)  // Returns true, because 11 div 10 is 1 (therefore, >= 1 is true).
(11<= 12)  // Returns true, because 11 is less than 12.
((11 div 10) > 1)  // Returns false, because 11 div 10 is 1.
(11 div 10) < 1)  // Returns false, because 11 div 10 is 1.
(11 != 12)  // Returns true, because 11 is not equal to 12.
(1 == 1) && (3 > 1)  // Returns true, because both expressions are true.

Приоритет операторов

Порядок вычисления составного выражения может быть важным. Например, дает другой результат в зависимости от того, (x + y / 100) выполняется ли добавление или деление. Скобки (()) можно использовать для явного указания компилятору, как он должен оценивать выражение. Например, можно указать (x + y) / 100. Если вы явно не сообщаете компилятору порядок выполнения операций, порядок основан на приоритете, назначенном операторам. Например, оператор деления имеет более высокий приоритет, чем оператор сложения. Поэтому для выражения x + y / 100компилятор сначала вычисляет y / 100 . Другими словами, x + y / 100 эквивалентно x + (y / 100). Чтобы упростить чтение и обслуживание кода, будьте явными. Используйте скобки, чтобы указать, какие операторы следует оценивать сначала. В следующей таблице перечислены операторы в порядке приоритета. Чем выше оператор отображается в таблице, тем выше приоритет. Операторы с более высоким приоритетом оцениваются перед операторами с более низким приоритетом. Обратите внимание, что приоритет оператора X++ не совпадает с приоритетом оператора других языков, таких как C# и Java.

Группы операторов в порядке приоритета Операторы
Unary - ~ !
Умножение, сдвиг, побитовая И, побитовая монопольная ИЛИ * / % DIV << >> & ^
Аддитивная, битовая инклюзивная ИЛИ + - |
Реляционная, равенство < <= == != > >= like as is
Логический (AND, OR) && ||
Conditional ? :

Операторы в одной строке имеют равный приоритет. Если выражение включает несколько из этих операторов, оно вычисляется слева направо, если не используются операторы назначения. (Операторы назначения оцениваются справа налево.) Например, && (логические AND) и || (логические OR) имеют одинаковый приоритет и оцениваются слева направо. Therefore:

  • 0 && 0 || 1 равно 1
  • 1 || 0 && 0 равно 0.