Jämförelse mellan X++ och C#

Anmärkning

Intressegrupper för communityn har nu flyttat från Yammer till Microsoft Viva Engage. Om du vill gå med i en Viva Engage-community och delta i de senaste diskussionerna fyller du i formuläret Begär åtkomst till Finance and Operations Viva Engage Community och väljer den community som du vill ansluta till.

I den här artikeln jämförs syntax och programmering för X++ och C#.

X++, C#-jämförelse: Hello World

I det här avsnittet jämförs det enklaste X++-programmet med dess motsvarighet i C#.

X++ till C#-jämförelser

I följande avsnitt beskrivs några grundläggande likheter och skillnader mellan X++ och C#.

Likheter

Följande X++-funktioner är desamma för C#:

  • Kommentarer med en rad (//) och flera rader (/* */).
  • == (lika) operator för att avgöra om två värden är lika.
  • != (inte lika med) operator för att avgöra om två värden inte är likvärdiga.
  • + operator (plustecken) för strängsammanfogning.

Differences

I följande tabell visas X++-funktioner som skiljer sig i C#.

Feature X++ C# Comments
if och else villkorsstyrda instruktioner -instruktionen if accepterar alla typer av uttryck som automatiskt kan konverteras till ett booleskt uttryck. Vanliga exempel är ett int för vilket 0 betyder false eller ett objekt som null betyder false för. Instruktionen if kräver ett booleskt uttryck. Syntaxstrukturen för klammerparenteser och parenteser är exakt densamma mellan X++ och C#.
Literalsträng En literalsträng kan avgränsas med någon av följande metoder:
  • Ett par dubbla citattecken (") tecken.
  • Ett par enkla citattecken (') tecken.
En literalsträng måste avgränsas med ett par dubbla citattecken (") tecken. För X++används vanligtvis tecken med dubbla citattecken för att avgränsa strängar. Det är dock praktiskt att avgränsa en sträng med enkla citattecken när strängen måste innehålla ett dubbelt citattecken.
röding type Det finns inte en char eller en teckentyp i X++. Du kan deklarera en str längd, men det är fortfarande en sträng:
str 1 myString = "a";
Det finns en char i C#. Du kan inte skicka en char som parameter till en metod som matar in en string parameter, även om du först uttryckligen kan konvertera char till en string. Mer information om X++-datatyper finns i Primitiva datatyper.
Utdata från meddelanden X++ levererar meddelanden till användaren i infolog-fönstret. Vanliga metoder är:
  • Utskriftsuttrycket:
  • statiska metoder för Global klassen:
    • Global::info
    • Global::warning
    • Global::error
För ett kommandoradsprogram kan meddelanden levereras till konsolen. Vanliga metoder är:
  • Console.Out.WriteLine
  • Console.Error.WriteLine

X++ och C#-exempel

Det här avsnittet innehåller två enkla kodexempel. Ett exempel är skrivet i X++, och det andra är i C#. Båda exemplen uppnår samma resultat. Följande X++-funktioner visas:

  • // kommentar med en rad
  • /\* \*/ kommentar med flera rader
  • if uttalande
  • == operatör
  • != operatör
  • + operator för att sammanfoga strängar
  • Global::info för meddelandeutdata, med och utan prefixet Global::
  • Global::error for message output
  • Användning av enkla och dubbla citattecken (' och ") som strängavgränsare.

Anmärkning

Det bästa sättet är att använda dubbla citattecken för alla strängar som kan visas för användaren.

X++-exempel

Det här X++-kodexemplet är i form av ett jobb. Det finns en nod med namnet Jobb i programobjektträdet (AOT). Det här exemplet kan läggas till under noden Jobb och sedan kan jobbet köras.

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.");
    }
}
Utgång

Här är utdata från Infolog-fönstret: Meddelande (09:49:48) Hello World, 1. Hello World, 2. Det här är som information, men gäller för varningar, 3. Det här är som information, men gäller för fel, 4.

C#-exempel

Följande C#-program är en omskrivning av det tidigare X++-programmet.

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.");
        }
    }
}
Utgång

Här är de faktiska utdata till C#-konsolen:

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#-jämförelse: Loopar

I det här avsnittet jämförs loopfunktionerna mellan X++ och C#.

Likheter

Följande funktioner är desamma i X++ och C#:

  • Deklarationer för variabler av den int primitiva datatypen. Deklarationer för andra primitiva typer är nästan desamma, men typerna kan ha olika namn.
  • while-instruktion för loopar.
  • break-instruktion för att avsluta en loop.
  • fortsätt -instruktionen för att hoppa upp till toppen av en loop.
  • <= (mindre än eller lika) jämförelseoperator.

Differences

I följande tabell visas X++-funktioner som skiljer sig i C#.

Features X++ C# Comments
-Instruktionen for . For-instruktionen är tillgänglig för loopar. C#- for instruktionen skiljer sig något från for I X++. I C# kan du deklarera räknar heltalet i -instruktionen for . Men i X++ måste räknaren deklareras utanför -instruktionen for .
++ inkrementsoperator. En ++-inkrementsoperator är tillgänglig i X++. Men en int-variabel som är dekorerad med ++ kan bara användas som en instruktion, inte som ett uttryck. Följande rader med X++-kod kompileras till exempel inte:
int age=42;
print age++;
Följande rader med X++-kod kompileras dock:
int age=42;
age++; print age;
C# ++-operatorn är mer flexibel än i X++. Följande kodrader är desamma på båda språken:
  • ++ myInteger;
  • myInteger++;
Men följande kodrader har en annan effekt än varandra och är endast giltiga i C#:
  • yourInt = ++myInt;
  • yourInt = myInt++;
modulooperator. I X++ är modulooperatorn mod. I C# är modulooperatorn %. Symbolerna för modulooperatorn är olika, men deras beteende är detsamma på båda språken.
Pausa tillfälligt ett konsolprogram som redan har påbörjats. -Instruktionen pause . I C# kan ett kommandoradsprogram pausas av följande kodrad:
Console.In.Read();
I X++ fortsätter du genom att klicka på en OK-knapp i en modal dialogruta. I C# fortsätter du genom att trycka på valfritt tangentbord på tangentbordet.
Visa ett meddelande. I X++visar -instruktionen print ett meddelande i utskriftsfönstret. I C# kan ett meddelande visas i konsolen med följande kodrad:
Console.WriteLine();
Funktionen X++ print används endast när du testar. Ett X++-program som använder nästan print alltid använder -instruktionen pause någonstans senare i koden. För X++-kod för produktion använder du metoden Global::info i stället för print. Funktionen strfmt används ofta tillsammans med info. Det finns ingen anledning att använda pause efter info.
Gör ett ljud. Pipfunktionen gör ett ljud som du kan höra. I C# utfärdas ett ljud som du kan höra av följande kodrad:
Console.Beep();
Var och en av uttrycken ger en kort ton.

X++-kodexemplen för loopar använder print funktionen för att visa resultat. I X++ kan du använda instruktionen print kan visa valfri primitiv datatyp utan att behöva anropa funktioner som konverterar den till en sträng först. Detta gör print det användbart i snabba testsituationer. I allmänhet används metoden Global::info oftare än print. Metoden info kan bara visa strängar. Därför används funktionen strfmt ofta tillsammans med info. En begränsning print är att du inte kan kopiera innehållet i utskriftsfönstret till Urklipp (till exempel med Ctrl+C). Global::info skriver till Infolog-fönstret som stöder kopiering till Urklipp.

Exempel 1: While Loop

Nyckelordet while stöder loopning i både X++ och C#.

X++ Exempel på när

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.
} 
Utgång

Utdata i X++-utskriftsfönstret är följande:

1
2
3
4

C#-exempel på

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();
    }
}
Utgång

Konsolens utdata från C#-programmet är följande:

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

Exempel 2: For Loop

Nyckelordet for stöder loopning i både X++ och C#.

X++ Exempel på för

I X++ kan inte räknarvariabeln deklareras som en del av for-instruktionen .

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;
}
Utgång

Utdata i X++-utskriftsfönstret är följande:

1
2
3
4

C# Exempel på för

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();
    }
}
Utgång

Konsolens utdata från C#-programmet är följande:

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#-jämförelse: Växla

I både X++ och C# omfattar switch-instruktionennyckelordsfall, bryt och standard. I följande tabell visas skillnaderna i switch-instruktionen mellan X++ och C#.

Feature X++ C# Comments
break; i slutet av varje skiftlägesblock I X++ körs alla andra skiftläges- och standardblock tills en instruktion har nåtts när ett ärendeblock matchar uttrycksvärdet på break;. Ingen break; instruktion krävs någonsin i en X++ -växelinstruktion , men break; instruktioner är viktiga i nästan alla praktiska situationer. I C# behövs alltid en break; instruktion efter -uttrycken i ett ärende eller standardblock . Om en case-sats inte har några instruktioner mellan sig själv och nästa fall-satsbreak; krävs ingen instruktion mellan de två skiftlägessatserna . Vi rekommenderar att du inte utelämnar -instruktionen break; efter ett ärendeblock, eftersom det kan förvirra nästa programmerare som redigerar koden.
break;i slutet av standardblocket I X++ finns det ingen effekt av att lägga till en break; instruktion i slutet av standardblocket . I C# kräver kompilatorn en break; instruktion i slutet av standardblocket . Mer information finns i Switch-instruktioner.
Endast konstanta värden i ett skiftlägesblock I X++ kan du ange antingen ett literalvärde eller en variabel i ett skiftlägesblock. Du kan till exempel skriva ärende myInteger:. I C# måste du ange exakt ett literalvärde för varje skiftlägesblock och inga variabler tillåts. Inga kommentarer.
Flera värden i ett skiftlägesblock I X++ kan du ange flera värden för varje skiftlägesblock. Värdena måste avgränsas med ett kommatecken. Du kan till exempel skriva case 4,5,myInteger:. I C# måste du ange exakt ett värde för varje skiftlägesblock . I X++ är det bättre att skriva flera värden i ett skiftlägesblock än att utelämna -instruktionen break; i slutet av ett eller flera skiftlägesblock.

Kodexempel för växel

I följande avsnitt visas jämförbara växelinstruktioner i X++ och C#.

Exempel på X++-växel

X++-växelexemplet visar följande:

  • case iTemp: och case (93-90): för att visa att skiftlägesuttryck inte är begränsade till konstanter, som de är i C#.
  • //break; för att visa att break; instruktioner inte krävs i X++, även om de nästan alltid är önskvärda.
  • case 2, (93-90), 5: för att visa att flera uttryck kan visas i en case-sats i 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
***

Exempel på C#-växel

I C#-växelexemplet visas följande:

  • fall 1: har en kommentar som förklarar att endast konstanta uttryck kan ges i en ärendesats .
  • break; -instruktioner inträffar efter den sista instruktionen i varje ärendeblock som har -instruktioner, vilket krävs av 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#-jämförelse: Strängfall och avgränsare

I det här avsnittet jämförs behandlingen av strängar med blandat hölje i X++ och C#. Den förklarar också de strängavgränsare som är tillgängliga i X++.

Likheter

Följande X++-funktioner är desamma som i C#:

  • Omvänt snedstreck (\) är escape-operatorn för strängavgränsare.
  • Vid-tecknet (@) nullifierar utrymningseffekten för omvänt snedstreck när vidtecknet skrivs omedelbart före det öppna citattecknet för en sträng.
  • Plustecknet (+) är strängsammanfogningsoperatorn.

Differences

X++-funktioner som skiljer sig i C# visas i följande tabell.

Feature X++ C# Comments
== Jämförelseoperator Okänsligt: operatorn == är okänslig för skillnader i stränghölje. I C# är operatorn == känslig för skillnader i stränghölje. I X++ kan du använda strCmp-funktionen för skiftlägeskänsliga jämförelser mellan strängar.
Strängavgränsare I X++ kan du använda antingen det enkla (') eller dubbla (") citattecknet som stränggränsare.

Not: Vanligtvis är bästa praxis att använda dubbla citattecken för strängar som kan visas för användaren. Det är dock praktiskt att avgränsa en sträng med enkla citattecken när ett dubbelt citattecken är ett av tecknen i strängen.

I C# måste du använda det dubbla citattecknet som stränggränsare. Detta refererar till typen System.String. I X++ och C# har du möjlighet att bädda in en avgränsare i en literalsträng och ta bort den med .
I X++ har du också alternativet att bädda in enkla citattecken i en sträng som avgränsas med dubbla citattecken (eller tvärtom) utan att behöva använda escape-koden.
Teckenavgränsare X++ har en strängdatatyp (str), men ingen teckentyp. I C# måste du använda det enkla citattecknet som teckengränsare. Detta refererar till typen System.Char. I .NET Framework är en System.String längd en annan datatyp än ett System.Char tecken.

Exempel 1: Skiftlägeskänslighet för operatorn ==

Operatorerna == och != är skiftlägesokänsliga i X++, men är skiftlägeskänsliga i C#, vilket visas i följande exempel.

X++ C# Comments
"HELLO" == "hello"
Sant i X++.
"HELLO" == "hello"
Falskt i C#.
Olika skiftlägesjämförelser mellan X++ och C#.

Exempel 2: Operatorn + Strängsammanfogning

Operatorerna + och += används för att sammanfoga strängar i både X++ och C#, vilket visas i exemplen i följande tabell.

X++ C# Comments
myString1 = "Hello" + " world";
Resultatet är likhet:
myString1 == "Hello world"
(Samma som för X++.) I både X++ och C#beror beteendet för operatorn + på datatypen för dess operander. Operatorn sammanfogar strängar eller lägger till tal.
mystring2 = "Hello";
myString2 += " world";
Resultatet är likhet: myString2 == "Hello world"
(Samma som för X++.) I både X++ och C#är följande instruktioner likvärdiga:
a = a + b;
a += b;

Exempel 3: Bädda in och ta bort strängavgränsare

Antingen enkla eller dubbla citattecken kan användas för att avgränsa strängar i X++. Escape-tecknet (\) kan användas för att bädda in avgränsare i en sträng. Dessa illustreras i följande tabell.

X++ C# Comments
myString1 = "They said \"yes\".";
Resultat:
They said "yes".
(Samma som för X++.) Med escape-tecknet kan du bädda in strängavgränsare inuti strängar.
myString2 = 'They said "yes".';
Resultat:
They said "yes".
C#-syntax tillåter inte att enkla citattecken avgränsar strängar. För strängar som användaren kan se anses det vara bästa praxis att använda escape-tecknet i stället för de enkla citattecken som visas i exemplet.
myString3 = "They said 'yes'.";
Resultat:
They said 'yes'.
(Samma som för X++.) I X++ behandlas inte de enkla citattecknen som avgränsare om inte strängen börjar med en avgränsare med ett citattecken. I C# har det enkla citattecknet ingen särskild betydelse för strängar, och det kan inte användas för att avgränsa strängar. I C# är det enkla citattecknet den avgränsare som krävs för literaler av typen System.Char. X++ har ingen teckendatatyp.
str myString4 = 'C';
Här är den enkla offerten en stränggränsare.
char myChar4 = 'C';
Här är det enkla citattecknet en System.Char avgränsare, inte en System.String avgränsare.
X++ har ingen datatyp som motsvarar System.Char i .NET Framework. En X++-sträng som är begränsad till en längd på en är fortfarande en sträng, inte en teckendatatyp.

Exempel 4: Enkelt escape-tecken

Exempel som illustrerar det enkla escape-tecknet i indata eller utdata visas i följande tabell.

X++ C# Comments
myString1 = "Red\ shoe";
Resultat:
Red shoe
En literalsträng i C# kan inte innehålla de två teckensekvensen av escape följt av ett blanksteg, till exempel "\ ". Ett kompilatorfel inträffar. När X++-kompilatorn stöter på två teckensekvensen "\ " ignoreras det enda escape-tecknet.
myString2 = "Red\\ shoe";
Resultat:
Red\ shoe
(Samma som för X++.) I ett par escape-tecken negerar den första den speciella innebörden av den andra.

Jämförelse: Matrissyntax

Det finns likheter och skillnader i funktioner och syntax för matriser i X++ jämfört med C#.

Likheter

Sammantaget finns det mycket likheter i syntaxen och behandlingen av matriser i X++ och C#. Det finns dock många skillnader.

Differences

I följande tabell visas områden i []-syntaxen för matriser som skiljer sig åt för X++ och C#.

Kategori X++ C# Comments
Deklaration En matris deklareras med hakparenteser som läggs till i variabelnamnet. En matris deklareras med hakparenteser som läggs till i datatypen. int myInts[]; // X++

Not: En X++-matris kan inte vara en parameter i en metod.

int[] myInts; // C#

Deklaration Matrissyntaxen stöder endast primitiva datatyper, till exempel int och str. Syntaxen stöder inte klasser eller tabeller. Matrissyntaxen stöder primitiva datatyper och klasser. I X++ kan du använda matrisen Array för en matris med objekt.
Deklaration X++ är begränsat till matriser med en enda dimension (myStrings[8]). C# lägger till stöd för flerdimensionella matriser (myStrings[8,3]) och för ojämna matriser (myStrings[8][3]). I X++ kan du inte ha en matris med matriser. Det finns dock avancerad syntax för att begränsa mängden aktivt minne som en stor matris kan använda, vilket ser ut som den flerdimensionella syntaxen i C#: int intArray[1024,16];. Mer information finns i Bästa praxis prestandaoptimeringar: Växla matriser till disk.
Deklaration I X++ är en matris en speciell konstruktion, men det är inte ett objekt. I C# är alla matriser objekt oavsett syntaxvariationer. X++ har en matrisklass, men dess underliggande mekanism skiljer sig från matriser som skapats med hjälp av []-syntaxen. I C# använder alla matriser samma underliggande mekanism, oavsett om [] klassens syntax System.Array används i koden.
Length I X++ bestäms längden på en statisk matris i deklarationssyntaxen. I C# bestäms storleken på en matris när matrisobjektet konstrueras. När du använder [] deklarationssyntaxen i X++, behövs ingen ytterligare förberedelse innan du tilldelar värden till matrisen.
I C# måste du deklarera och sedan konstruera matrisen innan du tilldelar den.
Length En X++-matris kan ha en dynamisk längd som kan ökas även efter att populationen har börjat. Detta gäller endast när matrisen deklareras utan ett tal i []. Prestanda kan vara långsammare om längden på den dynamiska matrisen ökar många gånger. I C# kan längden på en matris inte ändras när längden har angetts. I följande fragment av X++-kod är endast matrisen myInts dynamisk och kan öka i storlek.
int myInts[];
int myBools[5];
myInts[2] = 12;
myInts[3] = 13;
myBools[6] = 26; //Error
Length Du kan hämta längden på vissa matriser med hjälp dimOf av funktionen . C#-matriser är objekt som har en Length egenskap. Inga kommentarer.
Indexering Matrisindexering är 1 baserat. Matrisindexering är 0-baserad. mtIntArray[0] skulle orsaka ett fel i X++.
Konstant I X++ uppnås ett konstant värde bäst med hjälp av direktivet #define precompiler. I C# kan du dekorera variabeldeklarationen med nyckelordsstrecket för att uppnå ett konstant värde. X++ har inget const-nyckelord . C# kan inte tilldela värden till variabler som skapas av dess #define förkompileringsdirektiv.

X++ och C#-exempel

Följande kodexempel visar hur matriser med primitiva datatyper hanteras. Det första exemplet finns i X++, och det andra exemplet finns i C#. Båda exemplen ger samma resultat.

X++-exempel

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]));
    }
}
Utgång

Utdata till informationsloggen är följande:

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#-exempel

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
Utgång

Utdata från C#-programmet till kommandoradskonsolen är följande:

-------- 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]

Ytterligare matrisliknande X++-funktioner

Containern är en särskild datatyp som är tillgänglig i X++. Det kan betraktas som liknar en matris eller liknar en List samling.

Jämförelse: Samlingar

I ett ekonomi- och driftprogram kan du använda X++ List -samlingsklassen. .NET Framework som används i C# har en liknande klass med namnet System.Collections.Generic.List.

Jämföra användningen av listklasserna

I följande tabell jämförs metoder i klassen X++ List med metoderna på System.Collections.Generic.List från .NET Framework och C#.

Feature X++ C# Comments
Samlingsdeklaration List myList; List<string> myList; X++-deklarationen innehåller inte den typ av element som ska lagras.
Iteratordeklaration ListIterator iter
ListEnumerator enumer;
IEnumerator<string> iter; I X++ har objektet ListIterator metoder som kan insert och delete objekt från List. X++ ListEnumerator kan inte ändra innehållet i List. I X++ ListEnumerator skapas objektet alltid på samma nivå som List. Detta gäller inte alltid för ListIterator.
Hämta en iterator new ListIterator (myList)
myList.getEnumerator()
myList.GetEnumerator() I både X++ och C# har listobjektet en getter-metod för en associerad uppräknare.
Konstruktor new List(Types::String) new List<string>() Information om vilken typ av objekt som ska lagras i klasserna List ges till konstruktorn i både X++ och C#.
Uppdaterar data Uppräknare – uppräknaren blir ogiltig om några objekt i List läggs till eller tas bort.
Iterator – iteratorn har metoder som infogar och tar bort objekt från List. Iteratorn är fortfarande giltig.
Uppräknare – uppräknaren blir ogiltig om några objekt i List läggs till eller tas bort. Uppräknare blir ogiltiga när objekt har lagts till eller tagits bort från List, i både X++ och C#.
Uppdaterar data I X++ List har klassen metoder för att lägga till objekt i början eller slutet av listan. I C# List har klassen metoder för att lägga till medlemmar på valfri plats i listan. Den har också metoder för att ta bort objekt från valfri position. I X++ kan objekt tas bort från den List enda av en iterator.

Exempel 1: Deklaration av en lista

Följande kodexempel finns i X++ och C# som deklarerar List samlingar.

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

Exempel 2: Konstruktion av en lista

På båda språken måste typen av objekt som samlingsarkiven anges vid tidpunkten för konstruktionen. För klasstyper kan X++ inte bli mer specifik än om typen är en klass (Typer::Klass). Följande kodexempel finns i X++ och C#.

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

Exempel 3: Lägg till objekt i en lista

I både X++ och C# tillhandahåller samlingen en metod för att lägga till ett objekt i slutet av samlingen och för att infoga ett objekt i början. I C# innehåller samlingen en metod för att infoga när som helst i samlingen baserat på ett indexvärde. I X++ kan en samlings iterator infoga ett objekt vid dess aktuella position. Följande kodexempel finns i X++ och 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");

Exempel 4: Iterera genom en lista

Både X++ och C# har iteratorklasser som du kan använda för att gå igenom objekten i en samling enligt följande exempel.

// 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); 
}

Exempel 4b: foreach i C#

I C# används nyckelordet foreach ofta för att förenkla itereringsuppgiften genom en lista. Följande kodexempel fungerar på samma sätt som i föregående C#-exempel.

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

Exempel 5: Ta bort det andra objektet

I följande kodexempel tas det andra objektet bort från samlingen. I X++ krävs en iterator. I C# innehåller själva samlingen metoden för att ta bort ett objekt.

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

Exempel 6: Kombinera två samlingar

I följande kodexempel kombineras innehållet i två samlingar till en.

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

Jämförelse: Samlingar med nycklar med värden

I ett ekonomi- och driftprogram kan du använda samlingsklassen Map . Samlingen Map innehåller par med värden, nyckelvärdet plus ett datavärde. Detta liknar .NET Framework-klassen med namnet System.Collections.Generic.Dictionary.

Likheter

I följande lista beskrivs likheter mellan X++ och C# när det gäller deras samlingar som lagrar nyckel/värde-par:

  • Båda förhindrar dubbletter av nycklar.
  • Båda använder en uppräknare (eller iterator) för att loopa igenom objekten.
  • Båda nyckel/värde-samlingsobjekten skapas med beteckningar för de typer som lagras som nyckel och värde.
  • Båda kan lagra klassobjekt och är inte begränsade till att lagra primitiver som int.

Differences

I följande tabell beskrivs skillnaderna mellan X++ och C# när det gäller deras samlingsklasser som lagrar nyckel/värde-par:

Feature X++ C# Comments
Duplicerade nycklar I X++ Map förhindrar klassen dubbletter av nycklar genom att implicit behandla anropet till metoden insert som en åtgärd för att endast uppdatera värdet som är associerat med nyckeln. I C# Dictionary utlöser klassen ett undantag när du försöker lägga till en dubblettnyckel. Dubbletter av nycklar förhindras på båda språken, men med olika tekniker.
Ta bort objekt I X++ delete används metoden för ett iteratorobjekt för att ta bort ett oönskat nyckel/värde-par från en Map. I C# Dictionary har klassen en remove metod. På båda språken blir en uppräknare ogiltig om antalet samlingsobjekt ändras under uppräknarens livslängd.

Exempel 1: Deklaration av en Key-Value samling

På båda språken måste typen av objekt som nyckel/värde-samlingen lagrar anges. I X++ anges typen vid tidpunkten för konstruktionen. I C# anges typen både vid tidpunkten för deklarationen och tidpunkten för konstruktionen. Följande kodexempel finns i X++ och C#.

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

Exempel 2: Konstruktion av samlingen

På båda språken lagras den typ av objekt som nyckel/värde-samlingen lagrar under konstruktionen. För klasstyper kan X++ inte bli mer specifik än om typen är en klass (Typer::Klass). Följande kodexempel finns i X++ och C#.

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

Exempel 3: Lägg till ett objekt i samlingen

Det finns nästan ingen skillnad i hur ett objekt läggs till i en nyckel/värde-samling i X++ och C# enligt följande kodexempel.

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

Exempel 4: Iterera genom en Key-Value samling

Uppräknare används för att loopa igenom nyckel/värde-samlingarna i både X++ och C# enligt följande kodexempel.

// 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.
}

Exempel 5: Uppdatera värdet som är associerat med en nyckel

Syntaxen skiljer sig mycket mellan de två språken för en uppdatering av värdet som är associerat med en viss nyckel. Kodexemplen för ollowing är för nyckeln 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.”;

Exempel 6: Ta bort ett objekt

Syntaxen skiljer sig mycket mellan de två språken för att ta bort ett nyckel/värde-par från en samling, samtidigt som den itererar genom samlingsmedlemmarna. Kodexempel för nyckeln 102 visas nedan.

// 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);

Jämförelse: Undantag

Det finns vissa likheter men många skillnader när vi jämför undantagsrelaterat beteende mellan X++ och C#. Nyckelorden try, catch och throw beter sig likadant i X++ och C#. Men de typer av undantag som genereras och fångas är olika för de två språken.

Likheter

Likheter mellan X++ och C# när det gäller deras undantagsfunktioner är bland annat följande exempel:

  • Båda språken har samma nyckelord.
  • Båda har samma catch-nyckelord .
  • Båda aktiverar för en catch-instruktion som inte anger något särskilt undantag. En sådan catch-instruktion fångar upp alla undantag som når den.
  • Båda har samma nyckelord för att kasta .

Differences

Undantagsrelaterade skillnader mellan X++ och C# beskrivs i följande tabell.

Feature X++ C# Comments
Igen Hoppar till den första instruktionen i det associerade try-blocket . Mer information finns i Undantagshantering med prova och fånga nyckelord. Funktionen för nyckelordet för återförsök kan efterliknas i C#-kod, men det finns inget motsvarande nyckelord. Endast X++ har ett nyckelord för återförsök . C# har ingen motsvarighet. Mer information finns i X++, C#-jämförelse: Automatiserat återförsök efter ett undantag.
slutligen Nyckelordet finally stöds för att följa nyckelorden try och catch . Det sista nyckelordet markerar ett kodblock som följer försöks - och catch-blocken . Slutligen körs oavsett om något undantag genereras eller fångas. Semantiken är identisk med semantiken i C#.
Specifika undantag I X++ är ett undantag ett element i Exception uppräkningen, till exempel Fel, Dödläge eller CodeAccessSecurity. Inget undantag får innehålla ett annat. I C# är ett undantag en instans av basklassen System.Exception eller någon klass som ärver från den. Ett undantag kan finnas i InnerException egenskapen för undantaget som genereras. I X++ är varje undantag som genereras ett värde för undantagsuppräkningen. Mer information finns i Undantagsuppräkning.
Meddelande om undantag I X++ är meddelandet som skapas när ett undantag utlöses endast tillgängligt i Infolog och meddelandet är inte direkt kopplat till undantaget. I C# är Message meddelandet medlem i System.Exception objektet. I X++ är metoden Global::error den mekanism som visar undantagsmeddelanden i Infolog. Mer information finns i Undantagshantering med prova och fånga nyckelord.
Undantagsvillkor I X++ inträffar ett fel när du anropar en instansmetod på en objektvariabel som ännu inte har tilldelats något. Inget undantag utlöses dock tillsammans med det här felet. Därför kan inget catch block få kontroll även om den otilldelade variabeln missbrukas i ett try block. I följande kodexempel orsakar felet som orsakas av koden box4.toString(); inte att kontrollen överförs till något catch block: DialogBox box4;try { box4.toString(); info("toString did not error, but expected an error."); } catch (Exception::Error) // Inget undantagsvärde fångar detta. { info("Invalid use of box4 gave control to catch, unexpected."); } I C# utlöses en System.NullReferenceException när en ennitialiserad variabel behandlas som en objektreferens. Det kan finnas flera andra skillnader i villkoren som skapar undantag.
SQL-transaktioner I X++ när ett SQL-undantag inträffar i en ttsBegin - ttsCommit-transaktion kan ingen catch-instruktion i transaktionsblocket bearbeta undantaget. I C# kan ett catch-block i en SQL-transaktion fånga undantaget.

Examples

Följande X++-funktioner visas:

  • prova nyckelord.
  • catch keyword.
  • Beteendet efter ett undantag::Felfel inträffar.

X++-exempel

// 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.");
}
Utgång

Här är utdata från Infolog-fönstret:

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#-exempel

Följande C#-program är en omskrivning av det tidigare X++-programmet.

// 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
Utgång

Här är utdata till C#-konsolen:

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

Jämförelse: Automatiserat återförsök efter ett undantag

Ibland kan du skriva kod i ett catch-block som åtgärdar orsaken till ett undantag som inträffar under körningen. X++ innehåller ett nyckelord för återförsök som endast kan användas i ett catch-block . Nyckelordet försök igen gör det möjligt för ett program att gå tillbaka till början av try-blocket när problemet har korrigerats av kod i catch-blocket . C# har inget nyckelord för återförsök . C#-kod kan dock skrivas för att ge motsvarande beteende.

Kodexempel för återförsök

Följande X++-exempelprogram orsakar ett undantag::Fel utlöses. Detta inträffar när det först försöker läsa ett element från matrisen sStrings med hjälp av ett ogiltigt indexvärde. När undantaget fångas vidtas korrigerande åtgärder under körningen i fångstblocket . Återförsökssatsen hoppar sedan tillbaka till den första instruktionen i try-blocket . Den här andra iterationen fungerar utan att det uppstår något undantag.

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;
}

Utgång

Här är utdata till utskriftsfönstret:

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#-exempel

Följande C#-exempel är inte en rad-för-rad-översättning från föregående X++-exempel. I stället har C#-programmet en annan struktur så att det efterliknar beteendet för nyckelordet för återförsök som X++-programmet förlitar sig på. Försök och fånga block finns i en anropad metod. Variablerna som används i try-blocket lagras i anroparmetoden. Anroparmetoden skickar variablerna som parametrar som är dekorerade med ref-nyckelordet , så att deras värden kan korrigeras i fångstblocket för den anropade metoden. Den anropade metoden samlar in alla undantag och returnerar ett booleskt värde för att kommunicera tillbaka till anroparen om ett andra anrop krävs.

// 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;
    }
}

Utgång

Här är utdata till konsolen:

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.

Jämförelse: Operatorer

I det här avsnittet jämförs operatorerna mellan X++ och C#.

Tilldelningsoperatorer

I följande tabell visas skillnaderna mellan tilldelningsoperatorerna i X++ och C#.

X++ och C# Differences
= I X++ orsakar den här operatorn en implicit konvertering när en precisionsförlust kan inträffa, till exempel för en tilldelning från en int64 till en int. Men i C# orsakar tilldelningen ett kompileringsfel.
+= och -= Den enda skillnaden är att dessa operatorer i C# också används vid ombudsmanipulering.
++ och -- Det här är operatorerna för ökning och minskning på båda språken. Följande rad är identisk på båda språken:
++myInteger;
Men i X++ är dessa två operatorer för -instruktioner, inte för uttryck. Därför genererar följande rader kompileringsfel i X++:
myStr = int2str(++myInteger);
myIntA = myIntBB++;

Aritmetiska operatorer

I följande tabell visas de aritmetiska operatorerna.

X++ och C# Differences
* Som multiplikationsoperator finns det inga skillnader.

Not: Asterisken används också i SQL-uttryck som ingår i X++-språket. I dessa SQL-instruktioner kan asterisken också vara något av följande:

  • Ett jokertecken som anger att alla kolumner ska returneras.
  • Ett jokertecken för tecken i en sträng som används i en like-sats .
/ Divisionsoperatorn är densamma i X++ och C#.
MOD För moduloåtgärder är den enda skillnaden att symbolen % används i C#.
+ Additionsoperatorn är densamma i X++ och C#. Plustecknet används också för strängsammanfogning. Den här operatorn lägger till tal och sammanfogar strängar på båda språken.
- Subtraktionsoperatorn är densamma i X++ och C#.

Bitvis operatorer

I följande tabell jämförs bitvis operatorerna mellan X++ och C#.

X++ och C# Differences
<< Operatorn för vänster skift är densamma i X++ och C#.
>> Rätt skiftoperator är densamma i X++ och C#.
~ Operatorn BITWISE NOT är densamma i X++ och C#.
& Den binära AND-operatorn är densamma i X++ och C#.
^ Den binära XOR-operatorn är densamma i X++ och C#.

Relationsoperatorer

Följande relationsoperatorer är desamma i X++ och C#:

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

Jämförelse: Händelser

Det finns vissa skillnader i hur X++ och C# implementerar händelsedesignmönstret. Mer information finns i Händelseterminologi och Nyckelord.

Jämförelse av händelser mellan X++ och C#

Det finns skillnader i hur ombud används för händelser i X++ jämfört med C#.

Begrepp X++ C# Comments
delegate I X++kan ett ombud endast deklareras som medlem i en klass. Ett ombud kan inte vara medlem i en tabell. Alla ombud är instansmedlemmar i sin klass, inte statiska medlemmar. Ingen åtkomstmodifierare kan användas i en ombudsdeklaration eftersom alla ombud är skyddade medlemmar. Därför kan händelsen endast genereras med kod i samma klass där ombudet är medlem. Det enda undantaget för ett ombuds privata karaktär är dock att kod utanför deras klass kan fungera på ombuden med hjälp av operatorerna += och -= . I C# är varje ombud en typ, precis som varje klass är en typ. Ett ombud deklareras oberoende av vilken klass som helst. Utan nyckelordet event kan du ha ett ombud som parametertyp på en metod, precis som du kan ha en klass som parametertyp. Du kan skapa en instans av ett ombud för att skicka in för parametervärdet. I X++ är varje klass en typ, men inget ombud är en typ. Du kan inte skapa en instans av ett ombud. Inget ombud kan vara en parameter för en metod. Men du kan skapa en klass som har en delegatmedlem och du kan skicka instanser av klassen som parametervärden. Mer information finns i X++-nyckelord.
händelse I X++-kod är en händelse något av följande:
  • Ett explicit anrop till ett ombud.
  • Början eller slutet av en metod.
Det finns inget händelsenyckelord i X++.
I C# används händelsenyckelordet för att deklarera en ombudstyp som medlem i en klass. Effekten av händelsenyckelordet är att göra ombudet skyddat, men ändå tillgängligt för operatorerna += och -=. Du kan prenumerera på händelsehanterarmetoder till en händelse med hjälp av operatorn +=. Ett ombud kan vara användbart utan händelsenyckelordet , som en teknik för att skicka en funktionspekare som en parameter till en metod. De automatiska händelser som inträffar före början av en metod och efter en metods slut kan endast prenumereras på med hjälp av AOT.
Operatorerna += och -= I X++använder du operatorn += för att prenumerera på metoder för ett ombud. Operatorn -= avregistrerar en metod från ett ombud. I C#använder du operatorn += för att prenumerera på metoder för en händelse, eller till ett ombud som inte används med nyckelordet event . Ombudet innehåller en referens till alla objekt som har metoder som prenumererar på ombudet. Dessa objekt är inte berättigade till skräpinsamling medan ombudet innehåller dessa referenser.
eventHandler I X++ krävs nyckelordet eventHandler när du använder operatorn += eller -= för att prenumerera på eller avbryta prenumerationen på en metod från ett ombud. System.EventHandler är en ombudstyp i .NET Framework. Den här termen används på ett annat sätt i X++ än i C# eller .NET Framework. Mer information finns i X++-nyckelord.

X++-exempel

Viktiga saker att märka är följande i X++-exemplet:

  • XppClass har en delegatmedlem med namnet myDelegate.

    Anmärkning

    AOT innehåller en nod för ombudet. Noden finns i AOT > Classes > XppClass > myDelegate. Flera händelsehanterarnoder kan finnas under noden myDelegate. Händelsehanterare som representeras av noder i AOT kan inte tas bort av operatorn -= under körningstiden.

  • Klammerparenteserna {} i slutet av delegatdeklarationen krävs, men de kan inte ha någon kod i sig.

  • XppClass Har två metoder vars parametersignaturer är kompatibla med ombudet. En metod är statisk.

  • De två kompatibla metoderna läggs till i ombudet med operatorn += och nyckelordet eventHandler . Dessa instruktioner anropar inte händelsehanterarmetoderna, utan uttrycken lägger bara till metoderna i ombudet.

  • Händelsen genereras av ett anrop till ombudet.

  • Parametervärdet som skickades till ombudet tas emot av varje händelsehanterarmetod.

  • Det korta X++-jobbet längst upp i exemplet startar testet.

// 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);
    }
}

Utdata från det tidigare X++-jobbet är följande:

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#-exempel

Det här avsnittet innehåller ett C#-kodexempel för händelsedesignmönstret i föregående X++-exempel.

// 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);
    }
}

Utdata från föregående C#-exempel är följande:

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.

Händelser och AOT

Det finns andra händelsesystem som endast gäller för objekt i AOT. Mer information finns i Händelsehanterarnoder i AOT.

Jämförelse: Förkompileringsdirektiv

X++ och C# delar vissa nyckelord för sin precompiler-direktivsyntax, men innebörden är inte alltid densamma.

Likheter

X++ och C#-kompilatorerna känner igen många av samma nyckelord. I de flesta fall betyder nyckelorden samma sak för båda språkkompilatorerna.

Differences

En grundläggande skillnad mellan precompiler-direktiven i X++ och C# är det #define nyckelord som båda språkförkompilerarna känner igen. Till skillnad från C# kräver #define-direktivet i X++ en punkt i dess syntax. I X++ kan parenteser användas för att ge den definierade symbolen ett värde. Dessa skillnader visas i följande exempel:

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

En mindre skillnad är att det i C# kan finnas blanksteg och tabbtecken mellan #-tecknet och nyckelordet för direktivet, till exempel # define Testing.

Identiska nyckelord

I följande tabell visas förkompileringsdirektiv som liknar dem i X++ och C#.

Keyword X++ C# Comments
#define I X++kan ett namn på en precompiler-variabel definieras och ett värde kan ges till variabeln. I C#kan ett namn på en förkompilervariabel definieras, men det går inte att ange något värde för variabeln. Dessutom måste alla #define i C# ske överst i filen och kan inte inträffa efter någon kod, till exempel en användningsinstruktor eller en klassdeklaration. C#-kompilatorn kan ange en kommandoradsparameter /define för för att definiera ett namn på förkompilervariabeln utan att definiera variabeln i någon C#-kodfil. X++-kompilatorn har ingen motsvarighet till /define.
#if I X++kan #if avgöra om det finns en förkompilervariabel och om variabeln har ett angivet värde. I C# kan #if bara avgöra om det finns en förkompilervariabel. Det går inte att testa för något värde eftersom inget värde kan tilldelas.
#endif I X++ markerar #endif slutet på ett #if block. Det avslutar också ett #ifnot block. I C# markerar #endif slutet på ett #if block, oavsett om blocket innehåller en #else.

Olika nyckelord med samma bearbetningsresultat

I följande tabell visas förkompileringsdirektiv som namnges på olika sätt i X++ och C#, men som ger samma resultat när de bearbetas.

X++ C# Comments
#ifnot #if #else Det finns inget #else direktiv i X++, men #ifnot har liknande funktioner. I X++ kan #ifnot avgöra om det finns en förkompilervariabel och om variabeln inte har ett specifikt angivet värde. I C# kan #if avgöra om en precompiler-variabel finns när "!" symbolen är prefixet till variabelnamnet.
//BP Deviation documented #pragma varning Dessa X++ och C#-poster är inte likvärdiga, men det finns en partiell likhet. Båda utelämnar kompilatorvarningsmeddelanden.
#macrolib . HPP-fil i C++ Det finns en partiell likhet mellan X++-direktivet #macrolib jämfört med en . HPP-fil i C++. Båda kan innehålla flera #define-instruktioner.

Förkompileringsdirektiv exklusivt för X++

I följande tabell visas X++ precompiler-direktiv som inte har någon direkt motsvarighet i C#.

X++ Comments
#linenumber Det #linenumber direktivet är till för att hämta radnumret, så att det kan matas ut till informationsloggen.
C#-direktivet #line skiljer sig eftersom syftet är att ange radnumret.
#defdec #definc
#globaldefine I X++ finns det en liten skillnad mellan #globaldefine och #define. Skillnaden är att #globaldefine aldrig skriver över ett aktuellt värde som inte har tilldelats till en förkompilervariabel av #define.
C# har inget som liknar den här skillnaden, eftersom ett namn på förkompilervariabeln i C# inte kan ges ett värde.
#localmacro #macro I X++, #localmacro kan du tilldela ett flerradsvärde till en förkompilervariabel. #macro är en synonym, men #localmacro rekommenderas.
I C# har #define-direktivet en del av den här funktionen, men det kan inte tilldela ett värde till en precompiler-variabel.
#globalmacro I X++ är #globalmacro nästan samma som det önskade #localmacro.

Jämförelse: Objektorienterad programmering

De objektorienterade programmeringsprinciperna (OOP) för X++ skiljer sig från C#.

Konceptuella jämförelser

I följande tabell jämförs implementeringen av OOP-principer mellan X++ och C#.

Feature X++ C# Comments
Gjutning X++-språket har nyckelorden är och som, som används för att göra nedkastade filer säkra och explicita. Tips: X++ kräver inte användning av nyckelordet som när du nedarbetar en basklassvariabel till en härledd klassvariabel. Vi rekommenderar dock att alla nedslagna instruktioner använder som nyckelord. Ett objekt kan gjutas upp eller ned i arvssökvägen. Downcasts kräver som nyckelord. Mer information om nyckelorden X++ är och som finns i Uttrycksoperatorer: Är och Som för arv.
Lokala funktioner En metod kan innehålla en deklaration och kodtext för noll eller fler lokala funktioner. Endast den metoden kan ha anrop till den lokala funktionen. C# 3.0 stöder lambda-uttryck, som har vissa likheter med anonyma funktioner och lokala funktioner. Lambda-uttryck används ofta med ombud.
Metodöverlagring Metodöverlagring stöds inte. Ett metodnamn kan bara ske en gång per klass. Metodöverlagring stöds. Ett metodnamn kan inträffa flera gånger i en klass, med olika parametersignaturer i varje enskilt fall. X++ stöder valfria parametrar för metoder. Valfria parametrar kan delvis efterlikna metodöverlagring. Mer information finns i raden för valfria parametrar i den här tabellen.
Metodöversidosättning Metodöversidosättning stöds. En härledd klass kan ha en metod med samma namn som i basklassen, så länge parametersignaturen är densamma i båda fallen. Det enda undantaget är att den övergripande metoden kan lägga till ett standardvärde i en parameter. Metodöversidosättning stöds. Det virtuella nyckelordet måste tillämpas på en metod innan metoden kan åsidosättas i en härledd klass. Begreppet åsidosättande av en metod innehåller metodnamnet, dess parametersignatur och dess returtyp. Begreppet åsidosättning av metoder gäller inte om basmetoden och den övergripande metoden skiljer sig åt i någon av dessa aspekter.
Valfria parametrar En parameterdeklaration kan följas av en standardvärdetilldelning. Metodanroparen har möjlighet att skicka ett värde för parametern eller ignorera parametern för att acceptera standardvärdet. Den här funktionen efterliknar metodöverlagring eftersom två anrop till samma metodnamn kan skicka olika antal parametrar. Varje parameter som har ett standardvärde måste följa den sista parametern som inte har något standardvärde. Valfria parametrar stöds av nyckelordet params . Även utan nyckelordet params kan metodöverlagring från anroparens synvinkel ge delvis liknande funktioner. Mer information finns i Parametrar och omfång och Använda valfria parametrar.
Enskilt arv Du kan härleda din X++-klass från en annan X++-klass med hjälp av nyckelordet extends i classDeclaration-noden i klassen i AOT. Ingen klass härleds implicit direkt från en annan klass. Om du vill att klassen ska härledas direkt från Object klassen måste du använda nyckelordet extends . Du kan bara ange en klass för nyckelordet extends .

Varning! När du ändrar en X++-basklass som andra klasser härleds från måste du kompilera om basklassen med hjälp av Kompilera framåt. Det här alternativet säkerställer att de härledda klasserna också kompileras om. För att säkerställa att de härledda klasserna också kompileras om högerklickar du på basklassnoden och klickar sedan på Add-Ins > Kompilera framåt. Alternativet att klicka på Kompilera > (eller trycka på F7-tangenten) är ibland otillräckligt för en basklassändring.

En klass kan implementera noll till många gränssnitt.

En X++-tabell ärver implicit från Common tabellen och från xRecord klassen.
C# använder nyckelordet extends för att härleda från en annan klass. Alla .NET Framework-klasser härleds implicit från System.Object klassen, såvida de inte uttryckligen härleds från en annan klass.

Nyckelordsjämförelser

I följande tabell visas de OOP-relaterade nyckelorden i X++ och C#.

Keyword X++ C# Comments
abstrakt Ingen skillnad.
klass De offentliga och privata modifierarna ignoreras i klassdeklarationer. Det finns inget begrepp om en namnområdesgruppering av klasser. Det finns inga punkter (.) i några klassnamn. Modifierarna offentliga och privata kan användas för att ändra klassdeklarationer. C# har också nyckelordet internt, vilket relaterar till hur klasser grupperas tillsammans i sammansättningsfiler. Det finns inte begreppet skyddad klass, utan endast skyddade medlemmar i en klass.
Sträcker sig En klassdeklaration kan ärva från en annan klass med hjälp av nyckelordet extends . Ett kolon (:) används där nyckelorden utökas och implementeras används i X++.
sist En slutlig metod kan inte åsidosättas i en härledd klass. Det går inte att utöka en slutlig klass. Nyckelordet som är förseglat för en klass innebär samma sak som det sista betyder för en X++-klass.
Implementerar En klassdeklaration kan implementera ett gränssnitt med hjälp av nyckelordet implementeringar .
interface Ett gränssnitt kan ange metoder som klassen måste implementera. Ett gränssnitt kan ange metoder som klassen måste implementera.
ny Det nya nyckelordet används för att allokera en ny instans av en klass. Sedan anropas konstruktorn automatiskt. Varje klass har exakt en konstruktor och konstruktorn heter new. Du kan bestämma vilka parametrar konstruktorn ska ange. Det nya nyckelordet används för att skapa en ny instans av en klass. Sedan anropas konstruktorn automatiskt. Själva konstruktormetoderna heter newinte , de har samma namn som klassen.

Not: Det nya nyckelordet kan också användas på en metod för att ändra hur metoden åsidosätter samma metod i basklassen.

Både X++ och C# förutsätter en standardkonstruktor för klasser som inte har någon konstruktor uttryckligen skriven i sin kod.
noll Ingen skillnad.
privat och skyddat De privata och skyddade nyckelorden kan användas för att ändra deklarationen för en klassmedlem. De privata och skyddade nyckelorden kan användas för att ändra deklarationen för en klassmedlem.
public En metod som inte ändras med offentlig, skyddad eller privat har standardåtkomstnivån offentlig. En metod som inte ändras med offentlig, skyddad eller privat har standardåtkomstnivån privat.
statisk En metod kan vara statisk, men ett fält kan inte göra det. Både metoder och fält kan vara statiska.
super Supernyckelordet används i en härledd klass för att få åtkomst till samma metod i basklassen. void method2()
{
// Call method2 method
// on the base class.
super();
}
Basnyckelordet används i en härledd klass för att få åtkomst till olika metoder i basklassen.
void method2()
{
// Call methods on
// the base class.
base.method2();
base.method3();
}
I C# finns det en särskild syntax för att använda bas för att anropa baskonstruktorn.
denna För ett anrop från en instansmetod till en annan i samma objekt krävs en kvalificerare för den anropade metoden. Nyckelordet är tillgängligt som en kvalificerare för det aktuella objektet. För ett anrop från en instansmetod till en annan i samma objekt krävs ingen kvalificerare för den anropade metoden. Det här nyckelordet är dock tillgängligt som en kvalificerare för det aktuella objektet. I praktiken kan nyckelordet vara användbart genom att visa IntelliSense-information.
finalize Klassen Object innehåller finalize -metoden. Metoden finalize är inte slutgiltig och kan åsidosättas. Metoden finalize verkar likna System.Object.Finalize metoden i C#, men i X++ finalize har metoden ingen särskild betydelse av något slag. Ett objekt tas automatiskt bort från minnet när den sista referensen till objektet slutar referera till objektet. Detta kan till exempel inträffa när den sista referensen hamnar utanför omfånget eller tilldelas ett annat objekt att referera till. Metoderna Finalize och Dispose är vanliga i vissa typer av klasser. Skräpinsamlaren Finalize anropar metoderna och Dispose när den förstörs och objektet. I C# System.GC.Collect kan metoden i .NET Framework anropas för att starta skräpinsamlaren. Det finns ingen liknande funktion i X++ eftersom X++ använder en deterministisk skräpinsamlare.
main Klasser som anropas från en meny har sin main metod anropad av systemet. Klasser som anropas från en kommandoradskonsol har sin Main metod anropad av systemet.

Jämförelse: Klasser

När du använder C# i .NET Framework grupperas klasser i namnområden. Varje namnområde fokuserar på ett funktionellt område, till exempel filåtgärder eller reflektion. Men när du använder klasserna i X++, finns det inga synliga grupper som ett namnområde.

Jämförelse: Klasser om reflektion

I X++ TreeNode ger klassen åtkomst till programobjektträdet (AOT). Klassen TreeNode är centrum för reflektionsfunktioner i X++. Klassen TreeNode och dess metoder kan jämföras med System.Reflection namnområdet i .NET Framework som C# använder.

I följande tabell visas flera klasser som är tillgängliga för dig när du skriver C#-kod. Det här är .NET Framework-klasser. För den här tabellen finns alla C#-klasser i System.Reflection namnområdet om inget annat anges. Varje rad visar motsvarande klass, eller klassmedlem, som är tillgänglig för dig när du skriver X++-kod.

X++ C# Comments
TreeNode System .Assembly Sammansättning är den första klassen som ska användas när ett C#-program måste samla in reflektionsinformation. Statiska metoder i klassen TreeNode X++ är utgångspunkten för reflektion i X++.
TreeNode System .Type Instansmetoder på TreeNode motsvarar instansmetoder på System.Type.
TreeNode .AOTgetSource MethodInfo Metoden AOTgetSource returnerar flera informationsdelar tillsammans i en sträng. Detta inkluderar X++-källkoden i -metoden. Däremot MethodInfo har en separat medlem för varje information.
TreeNode .AOTfirstChild TreeNode .AOTnextSibling TreeNode .AOTiterator AOTiterator MethodInfo[] (en matris) I C# GetMethods returnerar metoden på System.Type en matris med MethodInfo-objekt. Du kan loopa igenom matrisen med den vanliga tekniken att öka en indexerare. Däremot är X++-modellen att navigera i trädkontrollen för AOT. Metoderna TreeNode för AOTfirstChild och AOTnextSibling utför navigeringen. Som ett motsvarande alternativ är X++ AOTiterator -klassen utformad för att navigera i trädkontrollen för AOT. En klassnod är överordnad över flera metodnoder. Stegen AOTiterator genom underordnade noder, som returnerar var och en som en annan TreeNode instans. Ytterligare resurser de TreeNode metoder som heter AOTparent och AOTprevious.
TreeNode .AOTgetProperty TreeNode .AOTgetProperties TreeNode .AOTname PropertyInfo I X++ AOTgetProperties returnerar metoden en lång sträng som innehåller namn/värde-par för alla egenskaper för TreeNode. Metoden AOTname returnerar en sträng som endast innehåller värdet för namnegenskapen.
TreeNode .AOTsave TreeNode .AOTinsert System .Reflection .Emit (namnområde för klasser) Metoden AOTsave tillämpar ändringar från ett TreeNode objekt i X++-koden på AOT och ändringarna sparas. Ett stort kodexempel finns i TreeNode.AOTsave-metoden.

Jämförelse: Klasser om fil-I/O

Det finns flera klasser som utför I/O-åtgärder (file input and output). I .NET Framework som används i C# finns motsvarigheterna till dessa klasser i System.IO namnområdet.

I följande tabell visas flera .NET Framework-klasser för C# som finns i System.IO namnområdet. Varje rad i tabellen visar klassen eller metoden X++ som bäst motsvarar .NET Framework-klassen.

X++ C# Comments
BinaryIo FileStream BinaryReader BinaryWriter X++-klasser som BinaryIo den sträcker sig från den abstrakta klassen Io fungerar som en ström, och de fungerar också som läsare och författare för den strömmen. I C# är strömmen en separat klass från klassen som har mer specifika läs- och skrivmetoder.
TextBuffer MemoryStream Dessa klasser innehåller en minnesintern buffert och några av metoderna behandlar bufferten som om den vore en fil på hårddisken.
WINAPI::createDirectory WINAPI::folderExists WINAPI::removeDirectory Directory DirectoryInfo Path X++ kan använda statiska metoder i WINAPI klassen för många grundläggande operativsystemfunktioner som omfattar kataloger.
WINAPI::getDriveType DriveInfo DriveType Dessa klasser och metoder används för att hämta enhet relaterad information.
WINAPI::copyFile WINAPI::createFile WINAPI::d eleteFile WINAPI::fileExists File FileAttributes FileInfo X++ kan använda statiska metoder i WINAPI klassen för många grundläggande operativsystemfunktioner som omfattar filer.
CommaIo Comma7Io (Ingen motsvarande klass.) Dessa X++-klasser kan generera filer som Microsoft Excel kan importera. I X++ finns en EPPlus-biblioteksreferens tillgänglig för ytterligare interaktion med Excel.
AsciiIo TextIo FileStream TextReader TextWriter Dessa klasser använder olika kodsidor.
Io Stream StreamReader StreamWriter FileStream Dessa används ofta som basklasser som andra klasser utökar.
CodeAccessPermission FileIoPermission System.Security .CodeAccessPermission Namnområdet System.Security.Permissions innehåller följande klasser:
  • CodeAccessSecurityAttribute
  • FileIOPermissionAttribute
  • FileIOPermission
  • FileIOPermissionAccess
Begreppen och metoderna för assert, demandoch revertAssert gäller för båda språken. Metoderna och deny som är tillgängliga i C# är dock revertDeny inte tillgängliga i X++.

X++, ANSI SQL-jämförelse: SQL Select

I X++ skiljer sig syntaxen för SQL Select-instruktionen från ANSI-specifikationen (American National Standards Institute).

Välj enskild tabell

I följande tabell visas skillnader mellan select-uttrycken för X++ SQL och ANSI SQL.

Feature X++ SQL ANSI SQL Comments
Tabellnamn på från-satsen . Från-satsen visar en postbuffertinstans som deklareras från en tabell, till exempel från CustTable tabellen. Från-satsen visar ett tabellnamn, inte namnet på en buffert. Postbufferten har alla metoder som xRecordklassen har i X++.
Syntaxsekvens för ordningen efter kontra där satser. Order by-satsen måste visas före where-satsen . Order by-satsen måste visas efter från- eller kopplingssatsen . Group by-satsen måste följa samma syntaxpositioneringsregler som ordningen enligt nedan. Order by-satsen måste visas efter where-satsen . Where-satsen måste visas efter från- eller kopplingssatsen. I både X++ och ANSI SQL måste från - och kopplingssatserna visas före ordningen efter och var-satser .
Villkorsförnekelse. Utropstecknet ('!') används för negation. Nyckelordet inte används för negation. X++ stöder inte syntaxen !like. I stället måste du tillämpa ! operator till en sats.
Jokertecken för operatorn like . 0 till många – Asterisk ('*')
Exakt 1 – Frågetecken ('?')
0 till många – Procenttecken ("%")
Exakt 1 – Underbar ('_')
Logiska operatorer i where-satsen . Och – &
Eller – ||
Och – och
Eller – eller

Kodexempel

I följande kodexempel visas funktioner i föregående tabell.

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-nyckelord

Följande X++ SQL-nyckelord hör till dem som inte ingår i ANSI SQL:

  • korsföretag
  • firstonly100
  • forceliterals
  • forcenestedloop
  • forceplaceholders
  • forceselectorder
  • validtimestate

Kopplingssats

I följande tabell visas skillnader om kopplingsnyckelordet för X++ SQL och ANSI SQL.

Feature X++ SQL ANSI SQL Comments
Kolumnlista. Kolumnerna i kolumnlistan måste alla komma från tabellen som anges i from-satsen och inte från någon tabell i en kopplingssats . Kolumner i listan kan inte kvalificeras med deras tabellnamn. Kolumnerna i kolumnlistan kan komma från valfri tabell i från - eller kopplingssatserna . Det hjälper andra att underhålla koden när du kvalificerar kolumnerna i listan med deras tabellnamn. Mer information finns i Select Statements on Fields (Välj instruktioner för fält).
Syntax för kopplingssatsen . Kopplingssatsen följer where-satsen. Kopplingssatsen följer en tabell i from-satsen. I X++-kodexemplet är kopplingsvillkoren en likhet mellan SalesPoolId värden.
Inre nyckelord. Standardanslutningsläget är inre koppling. Det finns inget inre nyckelord. Standardanslutningsläget är inre koppling. Det inre nyckelordet är tillgängligt för att göra koden explicit. Det yttre nyckelordet finns i både X++ SQL och ANSI SQL.
Nyckelord till vänster och höger . Nyckelorden till vänster och höger är inte tillgängliga. Alla kopplingar finns kvar. Nyckelorden till vänster och höger är tillgängliga för att ändra kopplingsnyckelordet . Inga kommentarer.
Likhetsoperator. Operatorn för dubbel likhetstecken ('==') används för att testa likheten mellan två värden. Operatorn för enkel likhetstecken ('=') används för att testa likheten mellan två värden. Inga kommentarer.

Kodexempel

I följande kodexempel visas kopplingssyntaxen i 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);
    }
}

Aggregerade fält

I följande tabell visas några skillnader i hur aggregerade fält i listan med valda kolumner refereras mellan X++ SQL och ANSI SQL. Aggregeringsfält är de som härleds av funktioner som sum eller avg.

Feature X++ SQL ANSI SQL Comments
Alias för aggregerat fältnamn. Det aggregerade värdet finns i fältet som aggregerades. Du kan använda nyckelordet som för att tagga ett aggregeringsfält med ett namnalias. Aliaset kan refereras i efterföljande kod. Mer information finns i Sammanställda funktioner: Skillnader mellan X++ och SQL

Kodexempel

I följande kodexempel illustrerar anropet till informationsmetoden hur du refererar till aggregerade fält (se 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.
***/

Andra skillnader

I följande tabell visas andra skillnader i select-instruktionen mellan X++ SQL och ANSI SQL.

Feature X++ SQL ANSI SQL Comments
Nyckelordet har . Det finns inget nyckelord . Med nyckelordet med kan du ange filtervillkor för rader som genereras av gruppen efter -satsen. Inga kommentarer.
Null-resultat. Om where-satsen filtrerar ut alla rader på ett tag returneras ingen särskild antalsrad för att rapportera det. Om where-satsen filtrerar ut alla rader returneras en särskild antalsrad i ett val. Antalsvärdet är 0. Inga kommentarer.
Markörer för att navigera i returnerade rader. Instruktionen while select innehåller markörfunktioner. Alternativet är att använda nästa nyckelord. Du kan deklarera en markör för loopning genom de rader som returneras från en select-instruktion .
Från-sats . Nyckelordet från är valfritt när inga kolumner visas och endast en tabell refereras till. Följande två syntaxalternativ är likvärdiga:
select \* from tCustTable;
select tCustTable;
En select-instruktion kan inte läsas från en tabell om inte från-satsen används. I X++ SQL fyller den enkla select-instruktionen tabellbuffertvariabeln med den första raden som returnerades. Detta illustreras av följande kodfragment:
select \* from tCustTable;
info(tCustTable.Name);