Порівняння X++ і C#

Примітка

Групи інтересів спільноти тепер переміщено з Yammer до Microsoft Viva Engage. Щоб приєднатися до спільноти Viva Engage та взяти участь в останніх обговореннях, заповніть форму Запит на доступ до спільноти Viva Engage фінансів і операцій і виберіть спільноту, до якої потрібно приєднатися.

У цій статті порівнюються синтаксис і програмування X++ і C#.

Порівняння X++, C#: Hello World

У цьому розділі порівнюються найпростіші програми X++ зі своїм аналогом у C#.

Порівняння від X++ до C#

У наведених нижче розділах описано основні подібності та відмінності між X++ і C#.

Подібності

Такі функції X++ однакові для C#:

  • Однорядкові (//) і багаторядкові (/* */) примітки.
  • == (дорівнює) оператору для визначення того, чи рівні два значення.
  • != (не дорівнює) оператору для визначення того, чи не є два значення еквівалентними.
  • + Оператор (знак "плюс") для об'єднання рядків.

Відмінності

У таблиці нижче наведено функції X++, які відрізняються в C#.

Функція X++ C# Коментарі
if і else умовні інструкції Інструкція if приймає будь-який тип виразу, який можна автоматично перетворити на логічний вираз. Типові приклади: int значення 0 означає false або об'єкт, для якого null-значення означає false. Оператор if вимагає логічного виразу. Синтаксична структура фігурних фігурних дужок і дужок однакова між X++ і C#.
Літеральний рядок Текстовий рядок можна розділяти за допомогою будь-яких із наведених нижче способів.
  • Пара подвійних лапок (") символів.
  • Пара одинарних лапок (') символів.
Буквальний рядок має бути розділений парою подвійних лапок (") символів. Для X++символи подвійних лапок зазвичай використовуються для розділення рядків. Однак, якщо рядок має містити символ подвійної лапки, зручно розмежувати рядок з одним лапкою.
Чар type У X++немає char типу символів або символів. Ви можете оголосити str довжину, але це все одно рядок:
str 1 myString = "a";
char Є в C#. Не можна передати char параметр як метод введення string параметра, хоча спочатку його можна перетворити на charstring. Докладні відомості про типи даних X++ див. в статті Примітивні типи даних.
Вивід повідомлень X++ доставляє повідомлення користувачу у вікні Infolog. Серед поширених методів:
  • Інструкція для друку :
  • статичні методи для Global класу:
    • Глобальний::info
    • Глобальний::попередження
    • Глобальний::помилка
Для програми командного рядка повідомлення можуть надходити на консоль. Серед поширених методів:
  • Console.Out.WriteLine
  • Console.Error.WriteLine

Зразки X++ і C#

Цей розділ містить два простих зразки коду. Один зразок записується в X++, а інший – у C#. Обидва зразки досягають однакового результату. Продемонстровано такі функції X++:

  • // примітка з одним рядком
  • /\* \*/ багаторядковий коментар
  • if заява
  • == Оператор
  • != Оператор
  • + оператор для об'єднання рядків
  • Global::info for message output, with the Global:: prefix
  • Global::error for message output
  • Використання одинарних і подвійних лапок (' і ") як роздільників рядків.

Примітка

Радимо використовувати подвійні лапки для будь-якого рядка, який може відображатися користувачу.

X++ зразок

Цей зразок коду X++ має форму завдання. У дереві об'єктів застосунку (AOT) є вузол під назвою Завдання. Цей зразок можна додати під вузлом Завдання, а потім запустити завдання.

static void JobRs001a_HelloWorld(Args _args)
{
    if (1 == 1) 
    {
        // These two info() calls are identical to the X++ compiler.
        // The second form is the one typically used in X++.
        Global::info("Hello World, 1.");
        info('Hello World, 2.');
    }
    if (1 != 1)
    {
        error("This message will not appear.");
    }
    else
    {
        // These two methods are also from the Global class.
        // The + operator concatenates two strings.
        warning("This is like info, but is for warnings, 3.");
        error("This is like info, but is for errors, 4.");
    }
}
Вихідні дані

Ось результати з вікна Infolog: Повідомлення (09:49:48) Hello World, 1. Привіт, світ, 2. Це схоже на інформацію, але для попереджень, 3. Це схоже на інформацію, але для помилок, 4.

C# Зразок

Наступна програма C# – це переписування попередньої програми X++.

using System;
class Pgm_CSharp
{
    static void Main( string[] args )
    {
        new Pgm_CSharp().Rs001a_CSharp_HelloWorld();
    }
    void Rs001a_CSharp_HelloWorld()
    {
        if (1 == 1) 
        {
            Console .Out .WriteLine("Hello World, Explicit .Out , 1.");
            Console .WriteLine("Hello World, Implicit default to .Out , 2.");
        }
        if (1 != 1)
        {
            Console .Error .WriteLine("This message will not appear.");
        }
        else
        {
            Console .Error .WriteLine(".Error is like .Out, but can be for warnings, 3.");
            Console .Error .WriteLine(".Error is like .Out, but is for errors, 4.");
        }
    }
}
Вихідні дані

Ось фактичний результат на консолі C#:

Hello World, Explicit .Out, 1. 
Hello World, Implicit default to .Out, 2. 
.Error is like .Out, but can be for warnings, 3. 
.Error is like .Out, but is for errors, 4.

Порівняння X++, C#: цикли

У цьому розділі порівнюються функції циклу між X++ і C#.

Подібності

Наведені нижче функції однакові в X++ і C#:

  • Оголошення змінних типу примітивних даних int. Оголошення для інших примітивних типів майже однакові, але типи можуть мати різні імена.
  • інструкції для циклів.
  • break statement to exit a loop.
  • продовжити інструкцію, щоб перейти до вершини циклу.
  • <= (менше або дорівнює) оператор порівняння.

Відмінності

У таблиці нижче наведено функції X++, які відрізняються в C#.

Функції X++ C# Коментарі
Заява for . Інструкція доступна для циклів. Оператор C# for дещо відрізняється від for оператора X++. У C# можна оголосити ціле число лічильника for в інструкції. Але в X++ лічильник повинен бути оголошений поза інструкцією for .
++ оператор інкременту. Оператор збільшення ++ доступний у форматі X++. Але вбудовану змінну, прикрашену ++, можна використовувати лише як оператор, а не як вираз. Наприклад, такі рядки коду X++ не буде компілюватися:
int age=42;
print age++;
Однак скомпіляція наведених нижче рядків коду X++:
int age=42;
age++; print age;
Оператор C# ++ гнучкіший, ніж у X++. Такі рядки коду однакові в обох мовах:
  • ++ myInteger;
  • myInteger++;
Але наведені нижче рядки коду мають різний ефект один від одного та дійсні лише в C#:
  • yourInt = ++myInt;
  • yourInt = myInt++;
оператор модуло. У X++ оператор модуло має значення mod. У C# оператор модуло %. Символи для оператора модуло відрізняються, але їх поведінка однакова в обох мовах.
Тимчасово призупинити консольну програму, яка вже почалася. Заява pause . У C#програма командного рядка може бути призупинена таким рядком коду:
Console.In.Read();
У X++ ви продовжуєте, натиснувши кнопку OK у модальному діалоговому вікні. У C# ви продовжуєте натискати будь-яку клавіатуру на клавіатурі.
Відображення повідомлення. У X++оператор print відображає повідомлення у вікні "Друк". У C# повідомлення може відображатися на консолі за таким рядком коду:
Console.WriteLine();
Функція X++ print використовується лише під час перевірки. Програма X++, яка використовує print майже завжди, використовує pause оператор десь пізніше в коді. Для коду production X++ використовуйте метод Global::info замість print. Функція strfmt часто використовується разом із info. Немає причин для використання pause після info.
Звуковий сигнал. Функція звукового сигналу робить звук, який можна почути. У C# звук, який ви можете почути, видається таким рядком коду:
Console.Beep();
Кожна з інструкцій створює короткий тон.

Зразки коду X++ для циклів використовують print функцію для відображення результатів. У X++ оператор може print відображати будь-який примітивний тип даних без необхідності викликати функції, які спочатку перетворюють його на рядок. Це стане print в пригоді в ситуаціях швидкої перевірки. Зазвичай метод Global::info використовується частіше, ніж print. Метод info може відображати лише рядки. Тому функція strfmt часто використовується разом із info. print Обмеження полягає в тому, що не можна скопіювати вміст вікна "Друк" до буфера обміну (наприклад, за допомогою клавіш Ctrl+C). Global::info записує у вікно Infolog, яке підтримує копіювання до буфера обміну.

Приклад 1. The while Loop

Поки ключове слово підтримує циклію в X++ і C#.

X++ зразок часу

static void JobRs002a_LoopsWhile(Args _args)
{
    int nLoops = 1;
    while (nLoops <= 88)
    {
        print nLoops;
        pause;
        // The X++ modulo operator is mod.
        if ((nLoops mod 4) == 0)
        {
            break;
        }
        ++ nLoops;
    }
    beep(); // Function.
    pause; // X++ keyword.
} 
Вихідні дані

Вивід у вікні "Друк X++" має такий спосіб:

1
2
3
4

C# Зразок часу

using System;
public class Pgm_CSharp
{
    static void Main( string[] args )
    {
        new Pgm_CSharp().WhileLoops();
    }

    void WhileLoops()
    {
        int nLoops = 1;
        while (nLoops <= 88)
        {
            Console.Out.WriteLine(nLoops.ToString());
            Console.Out.WriteLine("(Press any key to resume.)");
            // Paused until user presses a key.
            Console.In.Read();
            if ((nLoops % 4) == 0) {
                break;
            }
            ++ nLoops;
        }
        Console.Beep();
        Console.In.Read();
    }
}
Вихідні дані

Вивід консолі з програми C# такий:

1
(Press any key to resume.)
2
(Press any key to resume.)
3
(Press any key to resume.)
4
(Press any key to resume.)

Приклад 2. The for Loop

Ключове слово підтримує циклію в X++ і C#.

X++ зразок для

У X++ змінну лічильника не можна оголосити як частину оператора для .

static void JobRs002a_LoopsWhileFor(Args _args)
{
    int ii; // The counter.
    for (ii=1; ii < 5; ii++)
    {
        print ii;
        pause;
        // You must click the OK button to proceed beyond a pause statement.
        // ii is always less than 99.
        if (ii < 99)
        {
            continue;
        }
        print "This message never appears.";
    }
    pause;
}
Вихідні дані

Вивід у вікні "Друк X++" має такий спосіб:

1
2
3
4

C# Зразок для

using System;
public class Pgm_CSharp
{
    static void Main( string[] args )
    {
        new Pgm_CSharp().ForLoops();
    }
    void ForLoops()
    {
        int nLoops = 1, ii;
        for (ii = 1; ii < 5; ii++)
        {
            Console.Out.WriteLine(ii.ToString());
            Console.Out.WriteLine("(Press any key to resume.)");
            Console.In.Read();
            if (ii < 99)
            {
                continue;
            }
            Console.Out.WriteLine("This message never appears.");
        }
        Console.Out.WriteLine("(Press any key to resume.)");
        Console.In.Read();
    }
}
Вихідні дані

Вивід консолі з програми C# такий:

1
(Press any key to resume.)
2
(Press any key to resume.)
3
(Press any key to resume.)
4
(Press any key to resume.)
(Press any key to resume.)

Порівняння X++, C#: Switch

У X++ і C#оператор перемикача включає в себе регістр ключових слів, розрив і значення за замовчуванням. У таблиці нижче наведено відмінності в операторі переходу між X++ і C#.

Функція X++ C# Коментарі
break; у кінці кожного блока інциденту У X++, коли будь-який блок інциденту відповідає значенню виразу в реченні перемикача , усі інші блоки інцидентів і стандартних блоків виконуються, доки break; не буде досягнуто інструкції. У операторі break; X++ жодна інструкція ніколи не потрібна, але break; твердження важливі практично в усіх практичних ситуаціях. У C# break; оператор завжди потрібен після операторів у випадку або стандартному блоці . Якщо речення інциденту не містить інструкцій між собою та наступним реченням інцидентуbreak;, між двома реченнями інциденту інструкція не потрібна. Ми рекомендуємо не опускати виписку break; після будь-якого блоку інциденту, оскільки вона може заплутати наступного програміста, який редагує код.
break; у кінці стандартного блоку У X++ немає ефекту додавання break; інструкції в кінці стандартного блоку. У C# компілятору потрібна інструкція break; в кінці стандартного блоку. Докладні відомості див. в статті Змінення операторів.
Лише постійні значення в блоці інциденту У X++ можна вказати значення літерала або змінну в блоці інциденту. Наприклад, можна написати регістр myInteger:. У C# потрібно вказати лише одне значення літерала для кожного блоку інциденту , і жодні змінні не дозволені. Немає приміток.
Кілька значень в одному блоці інциденту У X++ можна вказати кілька значень для кожного блоку інцидентів. Значення слід розділяти крапкою з комою. Наприклад, можна написати case 4,5,myInteger:. У C# потрібно вказати лише одне значення в кожному блоці інциденту . У X++ краще записати кілька значень в одному блоці інциденту , ніж пропустити інструкцію break; в кінці одного або кількох блоків інцидентів.

Приклади коду для переходу

У наведених нижче розділах відображаються порівняльні оператори перемикання в X++ і C#.

Приклад перемикача X++

У прикладі перемикача X++ показано таке:

  • case iTemp: і case (93-90): показати, що вирази інциденту не обмежуються константами, як у C#.
  • //break; щоб показати, що break; оператори не потрібні в X++, хоча вони майже завжди бажані.
  • case 2, (93-90), 5: щоб показати, що кілька виразів можна відобразити в одному реченні інциденту в X++.
static void GXppSwitchJob21(Args _args)  // X++ job in AOT &gt; Jobs.
{
    int iEnum = 3;
    int iTemp = 6;
    switch (iEnum)
    {
        case 1:
        case iTemp:  // 6
            info(strFmt("iEnum is one of these values: 1,6: %1", iEnum));
            break;
        case 2, (93-90), str2Int("5"):  // Equivalent to three 'case' clauses stacked, valid in X++.
            //case 2:
            //case (93-90):  // Value after each 'case' can be a constant, variable, or expression; in X++.
            //case str2Int("5"):
            info(strFmt("iEnum is one of these values: 2,3,5: %1", iEnum));
            //break;  // Not required in X++, but usually wanted.
        case 4:
            info(strFmt("iEnum is one of these values: 4: %1", iEnum));
            break;
        default:
            info(strFmt("iEnum is an unforeseen value: %1", iEnum));
            break;
            // None of these 'break' occurrences in this example are required for X++ compiler.
    }
    return;
}

/*** Copied from the Infolog:
Message (02:32:08 pm)
iEnum is one of these values: 2,3,5: 3
iEnum is one of these values: 4: 3
***

C# switch Example

У прикладі перемикача C# показано таке:

  • інцидент 1: містить примітку, у якій пояснюється, що в реченні інциденту можна надавати лише постійні вирази.
  • break; оператори виникають після останньої інструкції в кожному блоці інциденту , який містить інструкції, як це вимагає C#.
using System;
namespace CSharpSwitch2
{
    class Program
    {
        static void Main(string[] args)  // C#
        {
            int iEnum = 3;
            switch (iEnum)
            {
                case 1:  // Value after each 'case' must be a constant.
                case 6:
                    Console.WriteLine("iEnum is one of these values: 1,6: " + iEnum.ToString());
                    break;
                //case 2,3,5:  // In C# this syntax is invalid, and multiple 'case' clauses are needed.
                case 2:
                case 3:
                case 5:
                    Console.WriteLine("iEnum is one of these values: 2,3,5: " + iEnum.ToString());
                    break;
                case 4:
                    Console.WriteLine("iEnum is one of these values: 4: " + iEnum.ToString());
                    break;
                default:
                    Console.WriteLine("iEnum is an unforeseen value: " + iEnum.ToString());
                    break;
                // All 'break' occurrences in this example are required for C# compiler.
            }
          return;
        }
    }
}
/*** Output copied from the console:
>> CSharpSwitch2.exe
iEnum is one of these values: 2,3,5: 3
>>
***/

Порівняння X++, C#: рядок і роздільники

У цьому розділі порівнюються обробки рядків із змішаним корпусом у X++ і C#. Тут також пояснюється роздільники рядків, доступні в X++.

Подібності

Такі функції X++ збігаються з функціями C#:

  • Зворотна скісна риска (\) – це оператор виходу для роздільників рядків.
  • Знак при (@) дає значення null ефекту виходу зворотної скісної риски, коли знак "при" записується безпосередньо перед відкритими лапками рядка.
  • Знак "плюс" (+) – оператор об'єднання рядків.

Відмінності

Функції X++, відмінні від C#, наведено в таблиці нижче.

Функція X++ C# Коментарі
==оператор порівняння Нечутливий: == оператор нечутливий до відмінностей у корпусі рядка. У C# == оператор чутливий до відмінностей у корпусі рядків. У X++ можна використовувати функцію strCmp для порівняння між рядками з урахуванням регістру.
Роздільники рядків У X++ можна використовувати одинарний (') або подвійний (") лапки як роздільник рядків.

Примітка: Зазвичай рекомендовано використовувати подвійні лапки для рядків, які можуть відображатися користувачу. Однак зручно розмежувати рядок одним лапками, якщо подвійний лапок – один із символів у рядку.

У C# подвійний лапок слід використовувати як роздільник рядків. Це стосується типу System.String. У X++ і C# можна вбудувати роздільник у буквальний рядок і уникнути його за допомогою .
У X++ також є альтернатива вбудовування одинарних лапок у рядок, розділений подвійними лапками (або навпаки), без необхідності використання виходу.
Роздільники символів X++ має тип даних рядка (str), але не має типу символів. У C# одинарні лапки слід використовувати як роздільник символів. Це стосується типу System.Char. У .NET Framework довжина – це інший тип даних, System.String ніж System.Char символ.

Приклад 1. Чутливість регістра оператора ==

Оператори == та != нечутливі до регістра в X++, але чутливі до регістру в C#, як показано в наведеному нижче прикладі.

X++ C# Коментарі
"HELLO" == "hello"
True в X++.
"HELLO" == "hello"
False у C#.
Порівняння різних регістрів між X++ і C#.

Приклад 2. Оператор об'єднання + рядок

Оператори + і += використовуються для об'єднання рядків у X++ і C#, як показано в наведених нижче таблицях.

X++ C# Коментарі
myString1 = "Hello" + " world";
Результат – рівність:
myString1 == "Hello world"
(Те саме, що й для X++.) Поведінка оператора +в X++ і C#залежить від типу даних операндів. Оператор об'єднує рядки або додає числа.
mystring2 = "Hello";
myString2 += " world";
Результат – рівність: myString2 == "Hello world"
(Те саме, що й для X++.) У X++ і C#такі оператори еквівалентні:
a = a + b;
a += b;

Приклад 3. Роздільники рядків вбудовування та втечі

Одинарні або подвійні лапки можна використовувати для розділення рядків у X++. Символ виходу (\) можна використовувати для вбудовування роздільників у рядок. Вони ілюструються в наведеній нижче таблиці.

X++ C# Коментарі
myString1 = "They said \"yes\".";
Результат:
They said "yes".
(Те саме, що й для X++.) Символ виходу дає змогу вбудовувати роздільники рядків у рядки.
myString2 = 'They said "yes".';
Результат:
They said "yes".
Синтаксис C# не дозволяє розмежувати рядки в одинарних лапках. Для рядків, які може бачити користувач, рекомендовано використовувати символ виходу замість окремих лапок, як показано в прикладі.
myString3 = "They said 'yes'.";
Результат:
They said 'yes'.
(Те саме, що й для X++.) У X++одинарні лапки не вважаються роздільниками, якщо рядок не починається з одного роздільника лапок. У C# одинарний лапок не має особливого значення для рядків, і його не можна використовувати для розділення рядків. У C# одинарний лапок – це обов'язковий роздільник для літералів типу System.Char. X++ не має типу даних символів.
str myString4 = 'C';
Тут одинарні лапки – це роздільник рядків.
char myChar4 = 'C';
Тут одинарний лапок – це System.Char роздільник, а System.String не роздільник.
X++ не має типу даних, який відповідає System.Char .NET Framework. Рядок X++, обмежений довжиною, залишається рядком, а не типом даних символів.

Приклад 4. Single Escape Character

Приклади, які ілюструють один символ виходу у введеному або вихідному форматі, відображаються в наведеній нижче таблиці.

X++ C# Коментарі
myString1 = "Red\ shoe";
Результат:
Red shoe
Буквальний рядок у C# не може містити дві послідовності символів виходу, а потім пробіл, наприклад "\ ". Стається помилка компілятора. Коли компілятор X++ зустрічає послідовність двох символів "\", він видаляє один символ виходу.
myString2 = "Red\\ shoe";
Результат:
Red\ shoe
(Те саме, що й для X++.) У парі символів виходу перший знівелює особливе значення другого.

Порівняння: синтаксис масиву

Існують подібності та відмінності в функціях і синтаксисі масивів у X++ і C#.

Подібності

Загалом у синтаксисі та обробці масивів у X++ і C#є багато подібності. Однак є багато відмінностей.

Відмінності

У таблиці нижче наведено області синтаксису [] для масивів, які відрізняються для X++ і C#.

Категорія X++ C# Коментарі
Декларація Масив оголошується квадратними дужками, доданими до імені змінної. Масив оголошується квадратними дужками, доданими до типу даних. int myInts[]; // X++

Примітка: Масив X++ не може бути параметром методу.

int[] myInts; // C#

Декларація Синтаксис масиву підтримує лише примітивні типи даних, наприклад int і str. Синтаксис не підтримує класи або таблиці. Синтаксис масиву підтримує примітивні типи даних і класи. У X++ масив можна використовувати Array для масиву об'єктів.
Декларація X++ обмежено масивами одного виміру (myStrings[8]). C# додає підтримку для багатовимірних масивів (myStrings[8,3]) і для нерівних масивів (myStrings[8][3]). У X++ не можна використовувати масив масивів. Проте існує розширений синтаксис обмеження обсягу активної пам'яті, яку може споживати великий масив, який виглядає як багатовимірний синтаксис в C#: int intArray[1024,16];. Докладні відомості див. в статті Оптимізація продуктивності найкращої практики: заміна масивів на диск.
Декларація У X++ масив – це спеціальна конструкція, але це не об'єкт. У C# всі масиви є об'єктами незалежно від варіантів синтаксису. X++ має клас масиву, але його основний механізм відрізняється від масивів, створених за допомогою синтаксису []. У C# всі масиви використовують однаковий базовий механізм незалежно від того, чи використовується в коді синтаксис System.Array [] класу.
Довжина У X++ довжина масиву статичного розміру визначається в синтаксисі оголошення. У C# розмір масиву визначається під час створення об'єкта масиву. Під час використання синтаксису оголошення [] в X++більше не потрібно готуватися, перш ніж призначати значення масиву.
У C# потрібно оголосити, а потім побудувати масив, перш ніж призначати ньому.
Довжина Масив X++ може мати динамічну довжину, яку можна збільшити навіть після початку сукупності. Це стосується лише випадків, коли масив оголошується без числа в []. Продуктивність може сповільнитися, якщо довжина динамічного масиву збільшується в рази. У C# довжину масиву не можна змінити після встановлення довжини. У наведеному нижче фрагменті коду X++ лише myInts масив динамічний і може збільшитися.
int myInts[];
int myBools[5];
myInts[2] = 12;
myInts[3] = 13;
myBools[6] = 26; //Error
Довжина За допомогою dimOf функції можна отримати довжину деяких масивів. Масиви C# – це об'єкти, які мають властивість Length . Немає приміток.
Індексування Індексування масивів дорівнює 1. Індексування масивів дорівнює 0. mtIntArray[0] спричинить помилку в X++.
Константа У X++ постійне значення найкраще досягається за допомогою директиви #define precompiler. У C# можна прикрасити оголошення змінної констом ключового слова, щоб досягти постійного значення. X++ не містить конст-ключового слова. C# не може призначати значення змінним, створеним директивою #define precompiler.

Зразки X++ і C#

У наведених нижче зразках коду показано, як обробляються масиви примітивних типів даних. Перший зразок міститься в X++, а другий – у C#. Обидва зразки досягають однакових результатів.

X++ зразок

static void JobRs005a_ArraySimple(Args _args)
{
    #define.macroArrayLength(3)
    // Static length.
    str sSports[#macroArrayLength];
    // Dynamic length, changeable during run time.
    int years[];
    int xx;
    Global::warning("-------- SPORTS --------");
    sSports[#macroArrayLength] = "Baseball";
    for (xx=1; xx <= #macroArrayLength; xx++)
    {
        info(int2str(xx) + " , [" + sSports[xx] + "]");
    }
    warning("-------- YEARS --------");
    years[ 4] = 2008;
    years[10] = 1930;
    for (xx=1; xx <= 10; xx++)
    {
        info(int2str(xx) + " , " + int2str(years[xx]));
    }
}
Вихідні дані

Вивід у infolog такий:

Message (14:16:08)
-------- SPORTS --------
1 , []
2 , []
3 , [Baseball]
-------- YEARS --------
1 , 0
2 , 0
3 , 0
4 , 2008
5 , 0
6 , 0
7 , 0
8 , 0
9 , 0
10 , 1930

C# Зразок

using System;
public class Pgm_CSharp
{
    static public void Main( string[] args )
    {
        new Pgm_CSharp().ArraySimple();
    }
    private void ArraySimple()
    {
        const int const_iMacroArrayLength = 3;
        // In C# the length is set at construction during run.
        string[] sSports;
        int[] years;
        int xx;
        Console.WriteLine("-------- SPORTS --------");
        sSports = new string[const_iMacroArrayLength];
        sSports[const_iMacroArrayLength - 1] = "Baseball";
        for (xx=0; xx < const_iMacroArrayLength; xx++)
        {
            Console.WriteLine(xx.ToString() + " , [" + sSports[xx] + "]");
        }
        Console.WriteLine("-------- YEARS --------");
        // In C# you must construct the array before assigning to it.
        years = new int[10];
        years[ 4] = 2008;
        years[10 - 1] = 1930;
        for (xx=0; xx < 10; xx++)
        {
            Console.WriteLine(xx.ToString() + " , [" + years[xx].ToString() + "]");
        }
    }
} // EOClass
Вихідні дані

Вивід із програми C# до консолі командного рядка такий:

-------- SPORTS --------
0 , []
1 , []
2 , [Baseball]
-------- YEARS --------
0 , [0]
1 , [0]
2 , [0]
3 , [0]
4 , [2008]
5 , [0]
6 , [0]
7 , [0]
8 , [0]
9 , [1930]

Додаткові функції, подібні до масиву X++.

Контейнер – це спеціальний тип даних, доступний у X++. Його можна вважати схожим на масив або схожим List на колекцію.

Порівняння: Колекції

У програмі для фінансів і операцій можна використовувати клас колекції X++ List . .NET Framework, що використовується в C#, має схожий клас з ім'ям System.Collections.Generic.List.

Порівняння використання класів списків

У таблиці нижче порівнюються методи класу X++ List з методами System.Collections.Generic.List , які водяться з .NET Framework і C#.

Функція X++ C# Коментарі
Оголошення колекції List myList; List<string> myList; Оголошення X++ не містить тип елементів, які потрібно зберігати.
Оголошення ітератора ListIterator iter
ListEnumerator enumer;
Ітер рядка< IEnumerator>; У X++ ListIterator об'єкт містить методи, які можуть insert і delete елементи з List. X++ ListEnumerator не може змінити вміст List. У X++ ListEnumerator об'єкт завжди створюється на тому самому рівні, що Listй . Це не завжди вірно для ListIterator.
Отримання ітератора new ListIterator (myList)
myList.getEnumerator()
myList.GetEnumerator() У X++ і C#об'єкт List має метод геттера для пов'язаного нумератора.
Конструктор new List(Types::String) new List<string>() Відомості про тип об'єктів, які зберігаються всередині List класів, надаються конструктору в X++ і C#.
Оновлення даних Нумератор – нумератор стає неприпустимим, якщо додаються або видаляються будь-які елементи List .
Ітератор – ітератор містить методи вставлення та видалення елементів із List. Ітератор залишається дійсним.
Нумератор – нумератор стає неприпустимим, якщо додаються або видаляються будь-які елементи List . Нумератори стають неприпустимими після додавання або видалення елементів із List, як x++ так і C#.
Оновлення даних У X++ List клас має методи додавання елементів на початку або в кінці списку. У C# List клас має методи додавання учасників на будь-якій позиції в списку. Крім того, у ній є способи видалення елементів із будь-якого розташування. Елементи X++ можна видалити лише за List допомогою ітератора.

Приклад 1. Оголошення списку

Нижче наведено приклади коду в X++ і C#, які оголошують List колекції.

// X++
List listStrings ,list2 ,listMerged;
ListIterator literator;
// C#
using System;
using System.Collections.Generic;
List<string> listStrings ,list2 ,listMerged; IEnumerator<string> literator;

Приклад 2. Побудова списку

В обох мовах тип елементів, які зберігаються в колекції, потрібно вказати на момент будівництва. Для типів класів X++ може бути не більш специфічним, ніж тип класу (Types::Class). Нижче наведено приклади коду в X++ і C#.

// X++
listStrings = new List( Types::String );
// C#
listStrings = new List<string>;

Приклад 3. Додавання елементів до списку

У X++ і C#колекції передбачено метод додавання елемента до кінця колекції та вставлення елемента на початку. У C# колекція надає метод вставлення в будь-який момент колекції на основі значення індексу. У X++ ітератор колекції може вставити елемент у поточному розташуванні. Нижче наведено приклади коду в X++ і C#.

// X++
listStrings.addEnd ("StringBB."); 
listStrings.addStart ("StringAA.");
// Iterator performs a midpoint insert at current position. 
listIterator.insert ("dog");
// C#
listStrings.Add ("StringBB."); 
listStrings.Insert (0 ,"StringAA.");
// Index 7 determines the insertion point.
listStrings.Insert (7 ,"dog");

Приклад 4. Ітерація за списком

У X++ і C# є класи ітераторів, за допомогою яких можна переходити між елементами в колекції, як показано в наведених нижче прикладах.

// X++
literator = new ListIterator (listStrings); 
// Now the iterator points at the first item.

// The more method answers whether 
// the iterator currently points 
// at an item. 
while (literator.more()) 
{ 
    info(any2str (literator.value())); 
    literator.next(); 
}
// C#
literator = listStrings .GetEnumerator(); 
// Now enumerator points before the first item, not at the first item.

// The MoveNext method both advances the item pointer, and 
// answers whether the pointer is pointing at an item. 
while (literator.MoveNext()) 
{ 
    Console.WriteLine (literator.Current); 
}

Приклад 4b: foreach in C#

У C# ключове слово foreach часто використовується, щоб спростити завдання ітерації за допомогою списку. Наведений нижче приклад коду працює так само, як і в попередньому прикладі C#.

foreach (string currentString in listStrings)
{ 
    Console.WriteLine(currentString);
}

Приклад 5. Видалення другого елемента

У прикладах нижче наведено приклади видалення другого елемента з колекції. У X++ для цього потрібен ітератор. У C# колекція сама по собі надає метод видалення елемента.

// X++
literator.begin(); 
literator.next(); 
literator.delete();
// C#
listStrings.RemoveAt(1);

Приклад 6. Об'єднання двох колекцій

Приклади коду нижче об'єднують вміст двох колекцій в одну.

// X++
listStrings = List::merge(listStrings ,listStr3);
// Or use the .appendList method:
listStrings.appendList (listStr3);
// C#
listStrings.InsertRange(listStrings.Count ,listStr3);

Порівняння: колекції ключів зі значеннями

У програмі для фінансів і операцій можна використовувати клас колекції Map . Колекція Map містить пари значень, ключове значення та значення даних. Це нагадує клас .NET Framework з іменем System.Collections.Generic.Dictionary.

Подібності

У наведеному нижче списку описано подібності між X++ і C# щодо колекцій, у яких зберігаються пари з ключовими значеннями:

  1. Обидва розділи запобігають повторенню ключів.
  2. Обидва перелічення (або ітератор) використовуються для циклічного проходження елементів.
  3. Обидва об'єкти колекції ключових значень побудовано з позначеннями типів, які зберігаються як ключ і значення.
  4. Обидва об'єкти можуть зберігати об'єкти класу та не лише зберігати примітиви, як int.

Відмінності

У таблиці нижче описано відмінності між X++ і C# щодо класів колекцій, у яких зберігаються пари ключових значень:

Функція X++ C# Коментарі
Дублювання клавіш У X++ Map клас запобігає повторюваним ключам, неявно розглядаючи виклик до його insert методу як операцію оновлення лише значення, пов'язаного з ключем. У C# Dictionary клас створює виняток під час спроби додати повторюваний ключ. Повторювані клавіші не підтримуються в обох мовах, хоча і різними методами.
Видалення елементів У X++ delete метод об'єкта ітератора використовується, щоб видалити непотрібну пару ключ-значення з Mapоб'єкта . У C# Dictionary клас має remove метод. В обох мовах перелічення стає неприпустимим, якщо кількість елементів колекції змінюється протягом терміну служби нумератора.

Приклад 1. Оголошення колекції Key-Value

В обох мовах потрібно вказати тип елементів, які зберігаються в колекції ключових значень. У X++ тип визначається під час будівництва. У C# тип визначається як під час оголошення, так і під час будівництва. Нижче наведено приклади коду в X++ і C#.

// X++
Map mapKeyValue;
MapEnumerator enumer;
MapIterator mapIter;
// C#
Dictionary<int,string> dictKeyValue;
IEnumerator<SysCollGen.KeyValuePair<int,string>> enumer;
KeyValuePair<int,string> kvpCurrentKeyValuePair;

Приклад 2. Будівництво колекції

В обох мовах тип елементів, які зберігає колекція ключових значень, указаний під час будівництва. Для типів класів X++ може бути не більш специфічним, ніж тип класу (Types::Class). Нижче наведено приклади коду в X++ і C#.

// X++
mapKeyValue = new Map(Types::Integer, Types::String);
// C#
dictKeyValue = new Dictionary<int,string>();

Приклад 3. Додавання елемента до колекції

Майже немає різниці в тому, як елемент додається до колекції ключових значень у X++ і C#, як показано в наведених нижче прикладах коду.

// X++
mapKeyValue.insert(xx ,int2str(xx) + “_Value”);
// C#
dictKeyValue.Add(xx ,xx.ToString() + “_Value”);

Приклад 4. Ітерація за допомогою колекції Key-Value

Нумератори використовуються для циклічного використання колекцій ключових значень у X++ і C#, як показано в наведених нижче прикладах коду.

// X++ 
enumer = mapKeyValue.getEnumerator();
while (enumer.moveNext())
{
    iCurrentKey = enumer.currentKey();
    sCurrentValue = enumer.currentValue();
    // Display key and value here.
}
// C#
enumer = dictKeyValue.GetEnumerator();
while (enumer.MoveNext())
{
    kvpCurrentKeyValuePair = enumer.Current;
    // Display .Key and .Value properties=
    // of kvpCurrentKeyValuePair here.
}

Приклад 5. Оновлення значення, пов'язаного з ключем

Синтаксис дуже відрізняється від двох мов для оновлення значення, пов'язаного з заданим ключем. Приклади коду ollowing використовуються для ключа 102.

// X++
mapKeyValue.insert(
    102 ,
    ”.insert(), Re-inserted” + ” key 102 with a different value.”);
// C#
dictKeyValue[102] = 
    “The semi-hidden .item property in C#, Updated the value for key 102.”;

Приклад 6. Видалення одного елемента

Синтаксис дуже відрізняється від двох мов, щоб видалити одну пару ключових значень із колекції, ітерації між учасниками колекції. Нижче наведено приклади коду для ключа 102.

// X++
mapIter = new MapIterator(mapKeyValue);
//mapIter.begin();
while (mapIter.more())
{
    iCurrentKey = mapIter.key();
    if (104 == iCurrentKey)
    {
        // mapKeyValue.remove would invalidate the iterator.
        mapIter.delete();
        break;
    }
    mapIter.next();
}
// C#
dictKeyValue.Remove(104);

Порівняння: винятки

Є деякі подібності, але багато відмінностей, коли ми порівнюємо поведінку, пов'язану з винятком, між X++ і C#. Спробуйте,зловити та кинути ключові слова поводяться однаково в X ++ і C#. Але типи винятків, кинутих і спійманих, відрізняються для двох мов.

Подібності

Подібності між X++ і C# щодо їхніх функцій винятку включають такі приклади:

  • Обидві мови мають однакове ключове слово.
  • Обидва мають однакове ключове слово улову .
  • Обидва дають змогу використовувати інструкцію для вилову , яка не вказує певний виняток. Така інструкція зловити ловить всі винятки, які досягають його.
  • Обидва мають однакове ключове слово.

Відмінності

Відмінності між X++ і C# пов'язаними з винятком, описані в таблиці нижче.

Функція X++ C# Коментарі
Повторити Перехід до першої інструкції в пов'язаному блоці спроб . Докладні відомості див. в статті Обробка винятків із використанням ключових слів. Функціональність ключового слова "Повторити " можна імітувати в коді C#, але відповідного ключового слова немає. Лише X++ має ключове слово ще раз . C# не має аналога. Докладні відомості див. в статті Порівняння X++, C#: Автоматична повторна спроба після винятку.
зрештою Ключове finally слово підтримується для відстеження try ключових слів і catch ключових слів. Нарешті, ключове слово позначає блок коду, який слідує за спробоюі зловити блоки. Нарешті буде виконано незалежно від того, чи буде кинуто або спіймано будь-який виняток. Семантика ідентична семантиці в C#.
Певні винятки У X++ виняток – це елемент Exception нуму, наприклад Error, Deadlock або CodeAccessSecurity. Жоден виняток не може містити інший. У C# виняток – екземпляр базового System.Exception класу або будь-якого класу, який успадковує від нього. Виняток може міститися у InnerException властивості наявного винятку. У X++ кожен створений виняток – це значення переліку винятків. Докладні відомості див. в розділі Перелік винятків.
Повідомлення про виняток У X++ повідомлення, яке створюється, коли підіймається виняток, доступне лише в інфологу, і повідомлення безпосередньо не пов'язане з винятком. У C# повідомлення є Message учасником System.Exception об'єкта. У X++ метод Global::error – це механізм, який відображає повідомлення про виняткову ситуацію в інфологу. Докладні відомості див. в статті Обробка винятків із використанням ключових слів.
Умови винятку У X++ помилка виникає, коли ви викликаєте метод екземпляра для змінної об'єкта, якій ще нічого не призначено. Однак разом із цією помилкою не виникає винятку. Таким чином, жоден блок не catch може отримати контроль, навіть якщо непризначена змінна неправильно використовується в блоці try . У наведеному нижче прикладі помилка, спричинена кодом box4.toString(); , не призводить до передачі елемента керування до будь-якого catch блоку: DialogBox box4;try { box4.toString();info("toString did not error, but expected an error."); } catch (Exception::Error) // Значення винятку не ловить це. { info("Invalid use of box4 gave control to catch, unexpected."); } У C# a System.NullReferenceException піднімається, коли неініціалізована змінна розглядається як посилання на об'єкт. В умовах, які викликають винятки, може бути кілька інших відмінностей.
Транзакції SQL У X ++ коли виняток SQL відбувається в транзакції ttsBegin - ttsCommit , оператор улову в блоці транзакцій не може обробити виняток. У C# блокування улову в транзакції SQL може спіймати виняток.

Приклади

Продемонстровано такі функції X++:

  • спробуйте ключове слово.
  • зловити ключове слово.
  • Поведінка після винятку::Помилка.

X++ приклад

// X++
static void JobRs008a_Exceptions(Args _args)
{
    str sStrings[4];
    int iIndex = 77;
    try
    {
        info("On purpose, this uses an invalid index for this array: " + sStrings[iIndex]);
        warning("This message doesn't appear in the Infolog," + " it's unreached code.");
    }
    // Next is a catch for some of the values of
    // the X++ Exception enumeration.
    catch (Exception::CodeAccessSecurity)
    {
        info("In catch block for -- Exception::CodeAccessSecurity");
    }
    catch (Exception::Error)
    {
        info("In catch block for -- Exception::Error");
    }
    catch (Exception::Warning)
    {
        info("In catch block for -- Exception::Warning");
    }
    catch
    {
        info("This last 'catch' is of an unspecified exception.");
    }
    //finally
    //{
    //    //Global::Warning("'finally' is not an X++ keyword, although it's in C#.");
    //}
    info("End of program.");
}
Вихідні дані

Ось вивід із вікна Infolog.

Message (18:07:24)
Error executing code: Array index 77 is out of bounds.
Stack trace
(C)\Jobs\JobRs008a_Exceptions - line 8
In catch block for -- Exception::Error
End of program.

C# Зразок

Наступна програма C# – це переписування попередньої програми X++.

// C#
using System;
public class Pgm_CSharp
{
    static void Main( string[] args )
    {
        new Pgm_CSharp().Rs008a_CSharp_Exceptions();
    }
    void Rs008a_CSharp_Exceptions()
    {
        //str sStrings[4];
        string[] sStrings = new string[4];
        try
        {
            Console.WriteLine("On purpose, this uses an invalid index for this array: " + sStrings[77]);
            Console.Error.WriteLine("This message doesn't appear in the Infolog, it's unreached code.");
        }
        catch (NullReferenceException exc)
        {
            Console.WriteLine("(e1) In catch block for -- " + exc.GetType().ToString() );
        }
        catch (IndexOutOfRangeException exc)
        {
            Console.WriteLine("(e2) In catch block for -- " + exc.GetType().ToString() );
        }
        // In C#, System.Exception is the base of all
        // .NET Framework exception classes.
        // No as yet uncaught exception can get beyond
        // this next catch.
        catch (Exception exc)
        {
            Console.WriteLine("This last 'catch' is of the abstract base type Exception: "
                + exc.GetType().ToString());
        }
        // The preceding catch of System.Exception makes this catch of
        // an unspecified exception redundant and unnecessary.
        //catch
        //{
        //    Console.WriteLine("This last 'catch' is"
        //        + " of an unspecified exception.");
        //}
        finally
        {
            Console.WriteLine("'finally' is not an X++ keyword, although it's in C#.");
        }
        Console.WriteLine("End of program.");
    }
} // EOClass
Вихідні дані

Ось вивід на консоль C#:

(e2) In catch block for -- System.IndexOutOfRangeException
'finally' is not an X++ keyword, although it's in C#.
End of program.

Порівняння: автоматична повторна спроба після винятку

Іноді ви можете написати код у блоці вилову, що виправляє причину винятку, що виникає під час виконання. X++ – це ключове слово, яке можна використовувати лише в блоці вилову . Ключове слово "Повторити " дає змогу програмі повернутися до початку блоку спроб після того, як проблему виправлено за допомогою коду в блоці улову . У C# немає ключового слова для повторення . Однак код C# можна записати, щоб забезпечити еквівалентну поведінку.

Зразки коду для повторення

Наведена нижче програма X++ викликає виняткову ситуацію::Помилка. Це відбувається, коли він вперше намагається прочитати елемент із масиву sStrings за допомогою неприпустимого значення індексу. Коли виняток спійманий, під час виконання виконується дія всередині блоку улову . Після цього інструкція повторіть спробу повернеться до першої інструкції в блоці спроб . Ця друга ітерація працює без винятку.

static void JobRs008b_ExceptionsAndRetry(Args _args)
{
    str sStrings[4];
    str sTemp;
    int iIndex = 0;

    sStrings[1] = "First array element.";
    try
    {
        print("At top of try block: " + int2str(iIndex));
        sTemp = sStrings[iIndex];
        print( "The array element is: " + sTemp );
    }
    catch (Exception::Error)
    {
        print("In catch of -- Exception::Error (will retry)." + " Entering catch.");
        ++iIndex;
        print("In catch of -- Exception::Error (will retry)." + " Leaving catch.");
        // Here is the retry statement.
        retry;
    }
    print("End of X++ retry program.");
    pause;
}

Вихідні дані

Ось результат у вікні "Друк".

At top of try block: 0
In catch of -- Exception::Error (will retry). Entering catch.
In catch of -- Exception::Error (will retry). Leaving catch.
At top of try block: 1
The array element is: First array element.
End of X++ retry program.

C# Зразок

Наведений нижче зразок C# не є лінійним перекладом із попереднього зразка X++. Натомість програма C# має іншу структуру, тому вона імітує поведінку ключового слова повторення , на яке спирається програма X++. Блоки спроби та вилову називаються методом. Змінні, які використовуються в блоці спроб , зберігаються в методі абонента. Метод абонента передає змінні як параметри, прикрашені ключовим словом посилання , щоб їх значення можна було виправити всередині блоку вилову викликаного методу. Викликаний метод фіксує всі винятки та повертає логічне значення , щоб повернутися до абонента, чи потрібен другий виклик.

// C#
using System;
public class Pgm_CSharp
{
    static void Main(string[] args)
    {
        new Pgm_CSharp() .Rs008b_CSharp_ExceptionsAndRetry();
    }
    void Rs008b_CSharp_ExceptionsAndRetry() // Caller
    {
        int iIndex = -1
            , iNumRetriesAllowed = 3;
        bool bReturnCode = true; // Means call the callee method.
        for (int xx=0; xx <= iNumRetriesAllowed; xx++)
        {
            if (bReturnCode)
            {
                bReturnCode = this.Rs008b_CSharp_ExceptionsAndRetry_Callee(ref iIndex);
            }
            else
            {
                break;
            }
        }
        Console.WriteLine("End of C# caller method.");
    }
    
    private bool Rs008b_CSharp_ExceptionsAndRetry_Callee(ref int iIndex)
    {
        bool bReturnCode = true; // Means call this method again.
        string[] sStrings = new string[4];
        string sTemp;
        sStrings[0] = "First array element.";
        try
        {
            Console.WriteLine("At top of try block: " + iIndex.ToString());
            sTemp = sStrings[iIndex];
            Console.WriteLine( "The array element is: " + sTemp );
            bReturnCode = false; // Means do not call this method again.
        }
        catch (Exception)
        {
            Console.WriteLine("In catch of -- Exception. Entering catch.");
            ++iIndex; // The 'ref' parameter in C#.
            Console.WriteLine("In catch of -- Exception. Leaving catch.");
            //retry;
            // In C# we let the caller method do the work
            // that the retry keyword does in X++.
        }
        Console.WriteLine("End of C# callee method.");
        return bReturnCode;
    }
}

Вихідні дані

Ось вивід на консоль:

At top of try block: -1
In catch of -- Exception. Entering catch.
In catch of -- Exception. Leaving catch.
End of C# callee method.
At top of try block: 0
The array element is: First array element.
End of C# callee method.
End of C# caller method.

Порівняння: оператори

У цьому розділі порівнюються оператори між X++ і C#.

Оператори призначення

У таблиці нижче наведено відмінності між операторами призначення в X++ і C#.

X++ і C# Відмінності
= У X++ цей оператор призводить до неявного перетворення, коли може виникнути втрата точності, наприклад для призначення від int64 до int. Але в C# призначення призводить до помилки компіляції.
+= і -= Єдина відмінність полягає в тому, що в C# ці оператори також використовуються в делегування маніпуляцій.
++ і -- Це оператори інкременту та декременту в обох мовах. Такий рядок однаковий для обох мов:
++myInteger;
Але в X++ ці два оператори призначені для операторів, а не для виразів. Таким чином, наведені нижче рядки створюють помилки компіляції в X++:
myStr = int2str(++myInteger);
myIntA = myIntBB++;

Арифметичні оператори

У таблиці нижче наведено арифметичні оператори.

X++ і C# Відмінності
* Як оператор множення відмінностей немає.

Примітка: Зірочка також використовується в інструкціях SQL, які входять до мови X++. У цих інструкціях SQL зірочка також може бути однією з таких дій:

  • Символ узагальнення, який вказує на те, що потрібно повернути всі стовпці.
  • Символ узагальнення для символів у рядку, який використовується в реченні like .
/ Оператор ділення однаковий у X++ і C#.
MOD Для операцій модуло єдина відмінність полягає в тому, що символ % використовується в C#.
+ Оператор додавання однаковий у X++ і C#. Знак "плюс" також використовується для об'єднання рядків. Цей оператор додає числа та об'єднує рядки обома мовами.
- Оператор віднімання однаковий у X++ і C#.

Оператори порозрядні

У таблиці нижче порівнюються побітові оператори між X++ і C#.

X++ і C# Відмінності
<< Оператор зсуву ліворуч однаковий у X++ і C#.
>> Оператор зсуву вправо однаковий у X++ і C#.
~ Побітовий оператор NOT однаковий у X++ і C#.
& Двійковий оператор AND однаковий у X++ і C#.
^ Двійковий оператор XOR однаковий у X++ і C#.

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

Такі реляційні оператори однакові в X++ і C#:

  • ==
  • <=
  • <=
  • >
  • <
  • !=
  • &&
  • ||
  • !
  • ? :

Порівняння: події

Існують деякі відмінності в тому, як X++ і C# впроваджують шаблон розробки подій. Докладні відомості див. в статті Термінологія події та Ключові слова.

Порівняння подій між X++ і C#

Існують відмінності в тому, як представники використовуються для подій у X++ і C#.

Концепція X++ C# Коментарі
Представника У X++представник може бути оголошений лише членом класу. Представник не може бути учасником таблиці. Усі представники – це члени їхнього класу, а не статичні учасники. У оголошенні представника не можна використовувати модифікатор доступу, оскільки всі представники захищені . Таким чином, подію можна підняти лише за кодом у тому ж класі, де представник є учасником. Однак єдиний виняток приватного характеру представника полягає в тому, що код поза його класом може працювати з представниками за допомогою операторів += і -=. У C#кожен представник має тип, так само, як кожен клас – це тип. Представник оголошується незалежно від будь-якого класу. Без ключового слова події представник може мати тип параметра для методу так само, як і клас як тип параметра. Для значення параметра можна створити екземпляр представника. У X++кожен клас – це тип, але жоден представник не є типом. Не можна створити екземпляр представника. Жоден представник не може бути параметром методу. Але ви можете створити клас, який має члена-представника, і ви можете передавати екземпляри класу як значення параметрів. Докладні відомості див. в статті Ключові слова X++.
подія У коді X++ подія є однією з таких дій:
  • Явний виклик представнику.
  • Початок або кінець методу.
У X++немає ключового слова події .
У C#ключове слово події використовується, щоб оголосити тип представника членом класу. Ключове слово події полягає в тому, щоб представник був захищений, але все ще доступний для операторів += і -= . За допомогою оператора += можна підписатися на методи обробника подій на подію . Представник може бути корисним без ключового слова події, як метод передачі вказівника функції як параметра в метод. Автоматичні події, які відбуваються до початку методу та після завершення методу, можна підписати лише за допомогою AOT.
Оператори += і -= У X++оператор += використовується для підписки на метод представника. Оператор -= відписує метод від представника. У C#оператор += використовується для підписки на методи події або представника , який не використовується з ключовим словом події . Представник містить посилання на всі об'єкти, які мають методи, підписані на представника. Ці об'єкти не мають права на збирання сміття, а представник зберігає ці посилання.
eventHandler У X++ключове слово eventHandler обов'язкове, якщо ви використовуєте оператор += або -= для підписки або скасування підписки на метод від представника. System.EventHandler – це тип представника в .NET Framework. Цей термін використовується в X++ інакше, ніж у C# або .NET Framework. Докладні відомості див. в статті Ключові слова X++.

X++ приклад

Важливі речі, які слід помітити, наведено в прикладі X++:

  • Має XppClass представника з іменем myDelegate.

    Примітка

    AOT містить вузол для представника. Вузол розташовано в AOT > Classes > XppClass > myDelegate. Під вузлом myDelegate можна знайти кілька вузлів обробника подій. Обробники подій, представлені вузлами в AOT, не можна видалити оператором -= під час виконання.

  • Фігурні {} дужки в кінці оголошення представника обов'язкові, але вони не можуть мати в них код.

  • У XppClass ньому є два способи, підписи параметрів яких сумісні з представником. Один із методів статичний.

  • До представника додаються два сумісні методи з оператором += і ключовим словом eventHandler . Ці інструкції не називають методами обробника подій, інструкції лише додають методи представнику.

  • Подія викликається одним викликом представника.

  • Значення параметра, передане представнику, отримує кожен метод обробника подій.

  • Коротке завдання X++ у верхній частині прикладу запускає тест.

// X++
// Simple job to start the delegate event test.
static void DelegateEventTestJob()
{
    XppClass::runTheTest("The information from the X++ job.");
}
// The X++ class that contains the delegate and the event handlers.
class XppClass
{
    delegate void myDelegate(str _information)
    {
    }
    public void myEventSubscriberMethod2(str _information)
    {
        info("X++, hello from instance event handler 2: " + _information);
    }
    static public void myEventSubscriberMethod3(str _information)
    {
        info("X++, hello from static event handler 3: " + _information);
    }
    static public void runTheTest(str _stringFromJob)
    {
        XppClass myXppClass = new XppClass();
        // Subscribe two event handler methods to the delegate.
        myXppClass.myDelegate += eventHandler(myXppClass.myEventSubscriberMethod2);
        myXppClass.myDelegate += eventHandler(XppClass::myEventSubscriberMethod3);
        // Raise the event by calling the delegate one time,
        // which calls all the subscribed event handler methods.
        myXppClass.myDelegate(_stringFromJob);
    }
}

Вивід із попереднього завдання X++ такий:

X++, hello from static event handler 
3: The information from the X++ job. X++, hello from instance event handler 
2: The information from the X++ job.

C# Зразок

Цей розділ містить зразок коду C# для шаблону розробки події попереднього зразка X++.

// C#
using System;
// Define the delegate type named MyDelegate.
public delegate void MyDelegate(string _information);
public class CsClass
{
    protected event MyDelegate MyEvent;
    static public void Main()
    {
        CsClass myCsClass = new CsClass();
        // Subscribe two event handler methods to the delegate.
        myCsClass.MyEvent += new MyDelegate(myCsClass.MyEventSubscriberMethod2);
        myCsClass.MyEvent += new MyDelegate(CsClass.MyEventSubscriberMethod3);
        // Raise the event by calling the event one time, which
        // then calls all the subscribed event handler methods.
        myCsClass.MyEvent("The information from the C# Main.");
    }
    public void MyEventSubscriberMethod2(string _information)
    {
        Console.WriteLine("C#, hello from instance event handler 2: " + _information);
    }
    static public void MyEventSubscriberMethod3(string _information)
    {
        Console.WriteLine("C#, hello from static event handler 3: " + _information);
    }
}

Вивід із попереднього зразка C# такий:

CsClass.exe C#, hello from instance event handler 
2: The information from the C\# Main. C\#, hello from static event handler 
3: The information from the C\# Main.

Події та AOT

Є й інші системи подій, які застосовуються лише до елементів AOT. Докладні відомості див. в статті Вузли обробника подій у AOT.

Порівняння: Директиви передкомпілятора

X++ і C# мають кілька ключових слів для синтаксису директиви попереднього компілятора, але значення не завжди однакові.

Подібності

Компілятори X++ і C# розпізнають багато однакових ключових слів. У більшості випадків ключові слова означають однакові для обох компіляторів мови.

Відмінності

Основною відмінністю між директивами попереднього компілятора в X++ і C# є ключове слово #define, яке розпізнають обидва мовні компілятори. На відміну від C#, у X++ директиві #define потрібна крапка в синтаксисі. У X++дужки можна використовувати, щоб надати визначеному символу значення. Ці відмінності відображаються в таких прикладах:

  • У X++: #define. InitialYear(2003)
  • In C#: #define InitialYear

Незначна відмінність полягає в тому, що в C# можуть бути пробіли та символи табуляції між символом #і ключовим словом директиви, наприклад # define Testing.

Однакові ключові слова

У таблиці нижче наведено директиви попереднього компілятора, схожі на X++ і C#.

Ключове слово X++ C# Коментарі
#define У X++можна визначити ім'я змінної попередньої компілятора, і йому можна надати значення. У C#можна визначити ім'я змінної попередньої компілятора, але для цієї змінної не можна присвоїти жодне значення. Крім того, будь-які #define в C# мають виникнути у верхній частині файлу та не можуть виникнути після будь-якого коду, наприклад оператора або оголошення класу. Компілятор C# може ввести параметр командного /define рядка, щоб визначити ім'я змінної precompiler, не визначаючи змінну в будь-якому файлі коду C#. Компілятор X++ не має аналогів ./define
#if У X++#if може визначити, чи існує змінна попереднього компілятора та чи має змінна задане значення. У C##if можна визначити, чи існує змінна попереднього компілятора. Не вдалося перевірити значення, оскільки не можна призначити жодне значення.
#endif У X++#endif позначає кінець блоку #if. Він також закінчується блоком #ifnot. У C##endif позначає кінець блоку #if незалежно від того, чи містить блок #else.

Різні ключові слова з однаковим результатом обробки

У таблиці нижче наведено директиви попереднього компілятора, які називаються по-різному в X++ і C#, але вони дають однакові результати під час обробки.

X++ C# Коментарі
#ifnot #if #else У X++немає директиви #else, але #ifnot забезпечує аналогічні функції. У X++#ifnot можете визначити, чи існує змінна попереднього компілятора та чи не має змінна певне задане значення. У C##if може визначити, чи існує змінна попередньої компілятора, коли "!". символ префікса до імені змінної.
//BP Deviation documented попередження #pragma Ці записи X++ і C# не еквівалентні, але є часткова схожість. Обидва вони пригнічують попередження компілятора.
#macrolib . HPP-файл у C++ Існує часткова схожість між директивою X ++ #macrolib проти . HPP-файл у C++. Обидва можуть містити кілька #define операторів.

Директиви попереднього компілятора виключно для X++

У таблиці нижче наведено директиви попереднього компілятора X++, які не мають прямого аналога в C#.

X++ Коментарі
#linenumber Директива #linenumber призначена для отримання номера рядка, щоб його можна було вивести в infolog.
Директива C# #line інша, тому що її мета полягає у встановленні номера рядка.
#defdec #definc
#globaldefine У X++є невелика різниця між #globaldefine та #define. Відмінність полягає в тому, що #globaldefine ніколи не перезаписує поточне ненулляне значення, призначене змінну precompiler #define.
C# не має нічого подібного до цієї різниці, оскільки в C#ім'я змінної попереднього компілятора не може мати значення.
#localmacro #macro У X++#localmacro дає змогу призначити багаторядкове значення змінної попереднього компілятора. #macro є синонімом, але рекомендовано #localmacro.
У C#директива #define має частину цієї функції, але не може призначити значення змінній precompiler.
#globalmacro У X++#globalmacro майже такий самий, як і основний #localmacro.

Порівняння: об'єктно-орієнтоване програмування

Принципи об'єктно-орієнтованого програмування (OOP) X++ відрізняються від C#.

Концептуальні порівняння

У таблиці нижче порівнюються принципи OOP між X++ і C#.

Функція X++ C# Коментарі
Лиття Мова X++ містить ключові слова, які використовуються, щоб зробити downcasts безпечними та явними. Порада. X++ не вимагає використання ключового слова, коли ви знижуєте змінну базового класу до змінної класу, що походить. Проте радимо використовувати як ключове слово всі оператори downcast. Об'єкт можна відлити вгору або вниз по шляху успадкування. Для даункастів потрібне ключове слово. Докладні відомості про ключові слова X++ див. в статті Оператори виразів: Is і As for Inheritance.
Локальні функції Метод може містити оголошення та текст коду для нульових або більше локальних функцій. Лише цей метод може мати виклики до локальної функції. C# 3.0 підтримує вирази лямбди, які мають деяку схожість з анонімними функціями та локальними функціями. Вирази Lambda часто використовуються з представниками.
Перевантаження методу Перевантаження методу не підтримується. Ім'я методу може відбуватися лише один раз для кожного класу. Метод перевантаження підтримується. Ім'я методу може виникати кілька разів в одному класі з різними підписами параметрів у кожному окремому випадку. X++ підтримує необов'язкові параметри для методів. Необов'язкові параметри можуть частково імітувати перевантаження методу. Докладні відомості див. в рядку необов'язкових параметрів у цій таблиці.
Перевизначення методу Підтримується перевизначення методу. Похідний клас може мати метод з таким самим іменем, як і в базовому класі, якщо підпис параметра однаковий в обох випадках. Єдиний виняток полягає в тому, що метод перезаписування може додати стандартне значення до параметра. Підтримується перевизначення методу. Віртуальне ключове слово потрібно застосувати до методу, щоб його можна було перевизначено в похідному класі. Концепція перезаписування методу включає ім'я методу, його підпис параметра та тип його повернення. Концепція перезаписування методу не застосовується, якщо базовий метод і метод перевизначення відрізняються в будь-якому з цих аспектів.
Необов'язкові параметри Після оголошення параметра може бути призначено значення за промовчанням. Абонент методу може передавати значення для цього параметра або ігнорувати параметр, щоб прийняти стандартне значення. Ця функція імітує перевантаження методу, оскільки два виклики з однаковим іменем методу можуть передавати різну кількість параметрів. Кожен параметр зі значенням за промовчанням має відповідати останньому параметру, який не має значення за промовчанням. Необов'язкові параметри підтримуються ключовим словом params . Навіть без ключового слова params , з точки зору абонента, перевантаження методу може забезпечити частково схожі функціональні можливості. Докладні відомості див. в статті Параметри, визначення області та використання необов'язкових параметрів.
Односпадкове успадкування Ви можете отримати клас X++ з іншого класу X++, використовуючи ключове слово розширення в вузлі classDeclaration вашого класу в AOT. Жоден клас неявно не походить безпосередньо з іншого класу. Якщо ви хочете, щоб ваш клас походить безпосередньо з Object класу, потрібно використовувати ключове слово розширення . Для ключового слова розширення можна вказати лише один клас.

Увага! Якщо змінити базовий клас X++, з якого походять інші класи, потрібно повторно компілювати цей базовий клас за допомогою компіляції вперед. Цей параметр гарантує, що похідні класи також перекомпільовано. Щоб забезпечити повторне компіляція похідних класів, клацніть правою кнопкою миші вузол базового класу та виберіть Add-Ins > Скомпілювати вперед. Щоб змінити базовий клас, іноді недостатньо вибрати команду Побудувати > компіляція (або натиснути клавішу F7).

Клас може реалізувати нуль для багатьох інтерфейсів.

Таблиця X++ неявно успадковується від Common таблиці та від xRecord класу.
C# використовує ключове слово розширення для отримання від іншого класу. Усі класи .NET Framework неявно походять від System.Object класу, якщо вони явно не походять від іншого класу.

Порівняння ключових слів

У таблиці нижче наведено ключові слова, пов'язані з OOP, у клітинках X++ і C#.

Ключове слово X++ C# Коментарі
абстрактний Немає різниці.
клас Модифікатори загальнодоступні та приватні ігноруються в оголошеннях класів. Немає концепції групування просторів імен класів. Немає точок (.) в іменах класів. Модифікатори загальнодоступні та приватні можна використовувати для змінення оголошень класу. C# також має внутрішнє ключове слово, яке пов'язано з тим, як класи групуються разом у файлах складання. Немає концепції захищеного класу, лише захищених членів класу.
Розширює Оголошення класу може успадковуватись від іншого класу за допомогою ключового слова розширення . Двокрапка (:) використовується, коли ключові слова розширюються та впроваджуються в X++.
Остаточний Остаточний метод не можна перевизначени в похідному класі. Остаточний клас не можна розширити. Ключове слово, запечатаний у класі, означає те саме, що остаточне означає для класу X++.
Реалізує Оголошення класу може впроваджувати інтерфейс за допомогою ключового слова впроваджує .
інтерфейс Інтерфейс може вказувати методи, які має впроваджувати клас. Інтерфейс може вказувати методи, які має впроваджувати клас.
новий Нове ключове слово використовується для виділення нового екземпляра класу. Потім конструктор викликається автоматично. Кожен клас має лише один конструктор, і конструктор називається new. Ви можете вирішити, які параметри має вводити конструктор. Нове ключове слово використовується для створення нового екземпляра класу. Потім конструктор викликається автоматично. Самі методи конструктора не називаються new, вони мають таке саме ім'я, як і клас.

Примітка:Нове ключове слово також можна використовувати для методу, щоб змінити спосіб, у який метод перевизначає той самий метод у базовому класі.

Обидва X++ і C# передбачають стандартний конструктор для класів, які не мають конструктора, явно написаного в коді.
нуль Немає різниці.
приватний і захищений За допомогою приватних і захищених ключових слів можна змінювати оголошення учасника класу. За допомогою приватних і захищених ключових слів можна змінювати оголошення учасника класу.
загальнодоступних Метод, який не змінюється загальнодоступними, захищеними або приватними , має рівень доступу за замовчуванням для загальнодоступних. Метод, який не змінюється загальнодоступними, захищеними або приватними , має рівень доступу за замовчуванням приватний.
Статичні Метод може бути статичним, але поле не може. Обидва методи та поля можуть бути статичними.
Супер Супер ключове слово використовується в похідному класі, щоб отримати доступ до того ж методу на базовому класі. void method2()
{
// Call method2 method
// on the base class.
super();
}
Основне ключове слово використовується в похідному класі для доступу до різних методів базового класу.
void method2()
{
// Call methods on
// the base class.
base.method2();
base.method3();
}
У C#є спеціальний синтаксис, який використовується для виклику базового конструктора.
цей Для виклику з одного методу екземпляра до іншого на тому самому об'єкті потрібен обмежувач для викликаного методу. Ключове слово, доступне як обмежувач для поточного об'єкта. Для виклику з одного методу екземпляра до іншого на тому самому об'єкті об'єкт обмежувач для викликаного методу не обов'язковий. Однак це ключове слово доступне як обмежувач для поточного об'єкта. На практиці ключове слово може бути корисним, відображаючи відомості IntelliSense.
finalize Клас Object містить finalize метод. Метод finalize не остаточний, і його можна перевизначено. Метод схожий finalize на System.Object.Finalize метод в C#, але в X++ finalize метод не має особливого значення будь-якого типу. Об'єкт автоматично видаляється з пам'яті, коли останнє посилання на об'єкт припиняє посилатися на об'єкт. Наприклад, це може статися, коли останнє посилання виходить за межі області або призначається інший об'єкт для посилання. Finalize Методи та Dispose поширені в деяких типах класів. Збирач сміття називає Finalize і Dispose методи, коли він руйнує і об'єкт. У C#метод в .NET Framework можна викликати, System.GC.Collect щоб запустити збирач сміття. У X++ подібна функція відсутня, тому що X++ використовує детерміністичний збирач сміття.
main Класи, які викликаються з меню, мають свій main метод, викликаний системою. Класи, які викликаються з консолі командного рядка, мають свій Main метод, викликаний системою.

Порівняння: класи

Коли ви використовуєте C# в .NET Framework, класи групуються в простори імен. Кожен простір імен фокусується на функціональній області, як-от операції з файлами або відбиття. Однак під час використання класів у X++немає видимих груп, наприклад простору імен.

Порівняння: класи про відбиття

У X++ TreeNode клас надає доступ до дерева об'єктів application (AOT). Клас TreeNode – це центр функціональності відбиття в X++. Клас TreeNode і його методи можна порівняти із простором System.Reflection імен у .NET Framework, який використовує C# .

У таблиці нижче наведено кілька класів, доступних під час написання коду C#. Це класи .NET Framework. Для цієї таблиці всі класи C# знаходяться в System.Reflection просторі імен, якщо не вказано інше. У кожному рядку відображається відповідний клас або член класу, який доступний під час написання коду X++.

X++ C# Коментарі
TreeNode System .Assembly Складання – це перший клас, який використовується, коли програма C# має збирати відомості про відбиття. Статичні методи в класі TreeNode X++ – це відправна точка для відбиття в X++.
TreeNode System .Type Методи екземпляра TreeNode відповідають методам екземпляра на System.Type.
TreeNode .AOTgetSource MethodInfo Метод AOTgetSource повертає кілька фрагментів інформації в одному рядку. Це включає вихідний код X++ у методі. На відміну від цього, MethodInfo для кожного фрагмента інформації є окремий елемент.
TreeNode .AOTfirstChild TreeNode .AOTnextSibling TreeNode .AOTiterator AOTiterator MethodInfo[] (масив) У полі C#метод GetMethods повертає System.Type масив об'єктів MethodInfo. Ви можете циклічного масиву за допомогою загальної методики інкрементування індексатора. На відміну від цього, модель X++ полягає в навігації в елементі керування деревом AOT. TreeNode Методи AOTfirstChild навігації та AOTnextSibling їх виконання. Як еквівалентна альтернатива, клас X ++ AOTiterator призначений для навігації в елементі керування деревом AOT. Вузол класу є батьківським вузлом для кількох вузлів методу. Кроки AOTiterator , описані в дочірніх вузлах, повертають кожен із них як інший TreeNode екземпляр. Додаткові ресурси, TreeNode які називаються AOTparent методами та AOTprevious.
TreeNode .AOTgetProperty TreeNode .AOTgetProperties TreeNode .AOTname PropertyInfo У X++метод повертає довгий рядок, AOTgetProperties який містить пари імен для всіх властивостей TreeNode. Метод AOTname повертає рядок, який містить лише значення властивості імені.
TreeNode .AOTsave на TreeNode .AOTinsert System .Reflection .Emit (простір імен класів) Метод AOTsave застосовує зміни з TreeNode об'єкта в коді X++ до AOT, і зміни зберігаються. Великий зразок коду див. в статті Метод TreeNode.AOTsave.

Порівняння: класи про файл вводу-виводу

Є кілька класів, які виконують операції введення файлів і виводу (IO). У .NET Framework, що використовується в C#, аналоги цих класів розташовано в System.IO просторі імен.

У таблиці нижче наведено кілька класів .NET Framework для C#, які містяться в System.IO просторі імен. У кожному рядку таблиці відображається клас або метод X++, який найкраще відповідає класу .NET Framework.

X++ C# Коментарі
BinaryIo FileStream BinaryReader BinaryWriter X++ класів, наприклад BinaryIo , які простягаються від абстрактного класу Io , служать потоком, і вони також служать читачем і письменником для цього потоку. У C#потік – це окремий клас від класу, який має більш конкретні методи читання та записування.
TextBuffer MemoryStream Ці класи містять буфер у пам'яті, а деякі методи обробляють буфер так, ніби це файл на жорсткому диску.
WINAPI::createDirectory WINAPI::folderExists WINAPI::removeDirectory Directory DirectoryInfo Path X++ може використовувати статичні методи в WINAPI класі для багатьох основних функцій операційної системи, які включають каталоги.
WINAPI::getDriveType DriveInfo на DriveType Ці класи та методи використовуються, щоб отримати пов'язану з диском інформацію.
WINAPI::copyFile WINAPI::createFile WINAPI::d eleteFile WINAPI::fileExists File FileAttributes FileInfo X++ може використовувати статичні методи в WINAPI класі для багатьох основних функцій операційної системи, які включають файли.
CommaIo на Comma7Io (Немає відповідного класу.) Ці класи X++ можуть створювати файли, які microsoft Excel може імпортувати. У X++ посилання на бібліотеку EPPlus доступне для додаткової взаємодії з Excel.
AsciiIo на TextIo FileStream TextReader TextWriter У цих класах використовуються різні кодові сторінки.
Io Stream StreamReader StreamWriter FileStream Вони часто використовуються як базові класи, які розширюються іншими класами.
CodeAccessPermission на FileIoPermission System.Security .CodeAccessPermission Простір імен System.Security.Permissions містить такі класи:
  • CodeAccessSecurityAttribute
  • FileIOPermissionAttribute
  • FileIOPermission
  • FileIOPermissionAccess
Поняття та методи assert, demandі revertAssert застосовуються до обох мов. Проте методи, denyrevertDeny доступні в C#, недоступні в X++.

X++, порівняння ANSI SQL: вибір SQL

У X++синтаксис інструкції вибору SQL відрізняється від специфікації Американського національного інституту стандартів (ANSI).

Вибір однієї таблиці

У таблиці нижче наведено відмінності між вибраними інструкціями X++ SQL і ANSI SQL.

Функція X++ SQL ANSI SQL Коментарі
Ім'я таблиці в реченні from . У реченні From перелічено екземпляр буфера записів, оголошений із таблиці, наприклад із CustTable таблиці. Речення From містить ім'я таблиці, а не ім'я буфера. Буфер запису містить усі методи, які xRecordклас має в X++.
Послідовність синтаксису порядку в порівнянні з реченнями. Речення order by має відображатися перед реченням where . Речення order by має відображатися після речення from або join . Речення group by має відповідати тим самим правилам розташування синтаксису, до яких відповідає порядок. Порядок за реченням має відображатися після речення WHERE . Речення where має відображатися після речення "Від " або "Об'єднання ". У X++ і ANSI SQL речення з і об'єднання мають відображатися перед реченнями order by і where .
Заперечення умов. Знак оклику ('!') використовується для заперечення. Не ключове слово використовується для заперечення. X++ не підтримує синтаксис !like. Замість цього, ви повинні застосувати ! оператором речення.
Символи узагальнення для подібного оператора. Від 0 до багатьох – Зірочка ('*')
Рівно 1 – знак питання ('?')
Від 0 до багатьох – знак відсотка ('%')
Точно 1 – підкреслення ('_')
Логічні оператори в реченні where . І – &
Або – ||
І – і
Або – або

Приклад коду

Наведений нижче приклад коду ілюструє функції в попередній таблиці.

static void OByWhere452Job(Args _args)
{
    // Declare the table buffer variable.
    CustTable tCustTable;
    ;
    while
    SELECT * from tCustTable
        order by tCustTable.AccountNum desc
        where (!(tCustTable.Name like '*i*i*') &amp;&amp; tCustTable.Name like 'T?e *')
    {
        info(tCustTable.AccountNum + " , " + tCustTable.Name);
    }
}
/*** InfoLog output
Message (04:02:29 pm)
4010 , The Lamp Shop
4008 , The Warehouse
4001 , The Bulb
***/

Ключові слова X++ SQL

Нижче наведено ключові слова X++ SQL, які не входять до складу ANSI SQL:

  • crosscompany
  • firstonly100
  • силітеральні засоби
  • forcenestedloop
  • покажчики місця заповнення
  • forceselectorder
  • validtimestate

Речення об'єднання

У таблиці нижче наведено відмінності в ключовому слові об'єднання X++ SQL і ANSI SQL.

Функція X++ SQL ANSI SQL Коментарі
Список стовпців. Стовпці в списку стовпців мають надходити з таблиці, указаної в реченні from , а не з будь-якої таблиці в реченні про об'єднання . Стовпці в списку не можуть бути кваліфіковані за іменем таблиці. Стовпці в списку стовпців можуть надходити з будь-якої таблиці в реченнях від або об'єднання . Це допомагає іншим користувачам підтримувати ваш код, коли ви відповідаєте критеріям для стовпців у списку з іменем таблиці. Докладні відомості див. в статті Вибір інструкцій у полях.
Синтаксис речення join. Речення join слідує за реченням where . Речення об'єднання слідує за таблицею в реченні from . У прикладі коду X++ умови об'єднання – це рівність SalesPoolId значень.
Внутрішнє ключове слово. Режим об'єднання за замовчуванням – внутрішнє об'єднання. Немає внутрішнього ключового слова. Режим об'єднання за замовчуванням – внутрішнє об'єднання. Внутрішнє ключове слово доступне, щоб зробити код явним. Зовнішнє ключове слово існує як в X++ SQL, так і в ANSI SQL.
Ключові слова ліворуч і праворуч . Ліві та праві ключові слова недоступні. Усі об'єднання залишаються. Ключові слова ліворуч і праворуч доступні для змінення ключового слова об'єднання . Немає приміток.
Оператор рівності. Оператор подвійного знака рівності (''==) використовується для перевірки рівності двох значень. Оператор єдиного знака рівності (''=) використовується для перевірки рівності двох значень. Немає приміток.

Приклад коду

Наведений нижче приклад коду ілюструє синтаксис об'єднання в X++ SQL.

static void OByWhere453Job(Args _args)
{
    // Declare table buffer variables.
    CustTable tCustTable;
    SalesPool tSalesPool;
    ;
    while
    SELECT
            // Not allowed to qualify by table buffer.
            // These fields must be from the table
            // in the from clause.
            AccountNum,
            Name
        from tCustTable
            order by tCustTable.AccountNum desc
            where (tCustTable.Name like 'The *')
        join tSalesPool
            where tCustTable.SalesPoolId == tSalesPool.SalesPoolId
    {
        info(tCustTable.AccountNum + " , " + tCustTable.Name);
    }
}

Агрегатні поля

У таблиці нижче наведено деякі відмінності в тому, як агрегатні поля в списку вибраних стовпців посилаються між X++ SQL і ANSI SQL. Агрегатні поля – це ті поля, які походять від таких функцій, як сума або середнє значення.

Функція X++ SQL ANSI SQL Коментарі
Псевдонім імені агрегатних полів. Сукупне значення міститься в полі, яке було агреговано. За допомогою ключового слова можна позначати зведене поле псевдонімом імені. На псевдонім можна посилатися в наступному коді. Докладні відомості див. в статті Агрегатні функції: відмінності між X++ і SQL

Приклад коду

У наведеному нижче прикладі коду виклик методу info ілюструє спосіб посилання на агрегатні поля (див tPurchLine.QtyOrdered. розділ ).

static void Null673Job(Args _args)
{
    PurchLine tPurchLine;
    ;
    while
    select
        // This aggregate field cannot be assigned an alias name.
        sum(QtyOrdered)
        from tPurchLine
    {
        info(
            // QtyOrdered is used to reference the sum.
            "QtyOrdered:  " + num2str(tPurchLine.QtyOrdered, 
            3,  // Minimum number of output characters.
            2,  // Required number of decimal places in the output.
            1,  // '.'  Separator to mark the start of the decimal places.
            2   // ','  The thousands separator.
            ));
    }
    info("End.");
}
/***
Message (12:23:08 pm)
QtyOrdered:  261,550.00
End.
***/

Інші відмінності

У таблиці нижче наведено інші відмінності вибіркової інструкції між X++ SQL і ANSI SQL.

Функція X++ SQL ANSI SQL Коментарі
Наявність ключового слова. Немає ключового слова. За допомогою ключового слова можна вказати умови фільтрування для рядків, створених групою за реченням. Немає приміток.
Null-результати. Якщо речення, де речення відфільтрує всі рядки, певний рядок лічильника не повертається, щоб повідомити про це. Якщо речення відфільтрує всі рядки у вибраному пункті, повертається спеціальний рядок лічильника. Значення лічильника – 0. Немає приміток.
Курсори для переміщення рядками, що повертаються. Інструкція вибору забезпечує функціональність курсору. Замість цього можна використовувати наступне ключове слово. Ви можете оголосити курсор для циклічного перегляду рядків, які повертаються з вибраної інструкції.
Речення From . Ключове слово від необов'язкове, якщо немає стовпців у списку, і на неї посилається лише одна таблиця. Такі два варіанти синтаксису еквівалентні:
select \* from tCustTable;
select tCustTable;
Вибіркову інструкцію не можна прочитати з таблиці, якщо не використовується речення from. У X++ SQL проста інструкція select заповнює змінну буфера таблиці першим рядком, який було повернуто. Цей фрагмент коду проілюстровано таким чином:
select \* from tCustTable;
info(tCustTable.Name);