Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Note
Les groupes d’intérêt communautaire sont maintenant passés de Yammer à Microsoft Viva Engage. Pour participer à une communauté Viva Engage et participer aux dernières discussions, renseignez le formulaire Demander l’accès à la communauté Finance et Operations Viva Engage , puis choisissez la communauté que vous souhaitez rejoindre.
Cet article compare la syntaxe et la programmation X++ et C#.
Comparaison X++, C# : Hello World
Cette section compare le programme X++ le plus simple à son équivalent en C#.
Comparaisons X++ vers C#
Les sections suivantes décrivent certaines similitudes et différences de base entre X++ et C#.
Similitudes
Les fonctionnalités X++ suivantes sont les mêmes pour C# :
- Commentaires à ligne unique (
//) et à plusieurs lignes (/* */). -
==Opérateur (égal) pour déterminer si deux valeurs sont égales. -
!=(pas égal à) opérateur pour déterminer si deux valeurs ne sont pas équivalentes. -
+(signe plus) pour la concaténation de chaîne.
Differences
Le tableau suivant répertorie les fonctionnalités X++ différentes en C#.
| Caractéristique | X++ | C# | Commentaires |
|---|---|---|---|
if et else instructions conditionnelles |
L’instruction if accepte tout type d’expression qu’elle peut convertir automatiquement en booléen. Les exemples courants incluent un int pour lequel 0 signifie false, ou un objet pour lequel la valeur null signifie false. |
L’instruction if requiert une expression booléenne. |
La structure de syntaxe concernant les accolades et parenthèses est exactement la même entre X++ et C#. |
| Chaîne littérale | Une chaîne littérale peut être délimitée à l’aide de l’une des méthodes suivantes :
|
Une chaîne littérale doit être délimitée par une paire de guillemets doubles (") caractères. | Pour X++, les guillemets doubles sont généralement utilisés pour délimiter les chaînes. Toutefois, il est pratique de délimiter une chaîne avec des guillemets simples lorsque votre chaîne doit contenir un guillemet double. |
carboniser type |
Il n’existe pas de char type de caractère dans X++. Vous pouvez déclarer une str longueur 1, mais il s’agit toujours d’une chaîne :str 1 myString = "a"; |
Il y a un char en C#. Vous ne pouvez pas passer un char paramètre en tant que paramètre à une méthode qui entre un string paramètre, bien que vous puissiez d’abord convertir explicitement le char en un string. |
Pour plus d’informations sur les types de données X++, consultez Types de données primitifs. |
| Sortie des messages | X++ remet des messages à l’utilisateur dans la fenêtre Infolog. Les méthodes courantes sont les suivantes :
|
Pour un programme de ligne de commande, les messages peuvent être remis à la console. Les méthodes courantes sont les suivantes :
|
Exemples X++ et C#
Cette section contient deux exemples de code simples. Un exemple est écrit en X++, et l’autre est en C#. Les deux exemples obtiennent le même résultat. Les fonctionnalités X++ suivantes sont illustrées :
-
//commentaire sur une seule ligne -
/\*\*/Commentaire sur plusieurs lignes - Instruction
if -
==opérateur -
!=opérateur -
+opérateur pour concaténer des chaînes - Global ::info pour la sortie du message, avec et sans le préfixe Global ::
- Global ::error pour la sortie du message
- Utilisation de guillemets simples et doubles (' et ") en tant que délimiteurs de chaîne.
Note
La meilleure pratique consiste à utiliser des guillemets doubles pour toute chaîne susceptible d’être affichée à l’utilisateur.
Exemple X++
Cet exemple de code X++ se présente sous la forme d’un travail. Il existe un nœud intitulé Travaux dans l’arborescence d’objets d’application (AOT). Cet exemple peut être ajouté sous le nœud Travaux, puis le travail peut être exécuté.
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.");
}
}
Output
Voici la sortie de la fenêtre Infolog : Message (09:49:48) Hello World, 1. Hello World, 2. C’est comme des informations, mais c’est pour les avertissements, 3. C’est comme des informations, mais c’est pour des erreurs, 4.
Exemple C#
Le programme C# suivant est une réécriture du programme X++ précédent.
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.");
}
}
}
Output
Voici la sortie réelle dans la console 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.
Comparaison X++, C# : boucles
Cette section compare les fonctionnalités de boucle entre X++ et C#.
Similitudes
Les fonctionnalités suivantes sont les mêmes dans X++ et C# :
- Déclarations pour les variables du type de données primitive int. Les déclarations d’autres types primitifs sont presque identiques, mais les types peuvent avoir des noms différents.
- while, instruction for loops.
- instruction break pour quitter une boucle.
- continuez l’instruction pour passer en haut d’une boucle.
- <= opérateur de comparaison (inférieur ou égal).
Differences
Le tableau suivant répertorie les fonctionnalités X++ différentes en C#.
| Fonctionnalités | X++ | C# | Commentaires |
|---|---|---|---|
Instruction for . |
L’instruction for est disponible pour les boucles. | L’instruction C# for est légèrement différente de for celle de X++. |
En C#, vous pouvez déclarer l’entier du compteur dans l’instruction for . Toutefois, dans X++, le compteur doit être déclaré en dehors de l’instruction for . |
| Opérateur d’incrément ++. | Un opérateur d’incrément ++ est disponible dans X++. Mais une variable int décorée avec ++ ne peut être utilisée qu’en tant qu’instruction, et non comme expression. Par exemple, les lignes de code X++ suivantes ne sont pas compilées :int age=42;print age++;Toutefois, les lignes de code X++ suivantes sont compilées : int age=42;age++; print age; |
L’opérateur C# ++ est plus flexible que dans X++. | Les lignes de code suivantes sont les mêmes dans les deux langues :
|
| opérateur modulo. | Dans X++, l’opérateur modulo est mod. | En C#, l’opérateur modulo est %. | Les symboles de l’opérateur modulo sont différents, mais leur comportement est le même dans les deux langues. |
| Suspendez temporairement un programme de console qui a déjà commencé. | Instruction pause . |
En C#, un programme de ligne de commande peut être suspendu par la ligne de code suivante :Console.In.Read(); |
Dans X++, vous continuez en cliquant sur un bouton OK dans une boîte de dialogue modale. En C#, vous continuez en appuyant sur n’importe quel clavier sur le clavier. |
| Afficher un message. | Dans X++, l’instruction print affiche un message dans la fenêtre Imprimer. |
Dans C#, un message peut s’afficher sur la console en suivant la ligne de code suivante :Console.WriteLine(); |
La fonction X++ print est utilisée uniquement lorsque vous testez. Un programme X++ qui utilise print presque toujours l’instruction pause quelque part plus loin dans le code. Pour le code X++ de production, utilisez la méthode Global ::info au lieu de print. La strfmt fonction est souvent utilisée avec info. Il n’y a pas de raison d’utiliser pause après info. |
| Faites un son. | La fonction de bip fait un son que vous pouvez entendre. | En C# un son que vous pouvez entendre est émis par la ligne de code suivante :Console.Beep(); |
Les énoncés produisent chacun un ton court. |
Imprimer et global ::info
Les exemples de code X++ pour les boucles utilisent la print fonction pour afficher les résultats. Dans X++, vous pouvez utiliser l’instruction print peut afficher n’importe quel type de données primitif sans avoir à appeler des fonctions qui la convertissent en chaîne en premier. Cela rend print utile dans les situations de test rapide. En règle générale, la méthode Global ::info est utilisée plus souvent que print. La info méthode ne peut afficher que des chaînes. Par conséquent, la fonction strfmt est souvent utilisée avec info. Une limitation print est que vous ne pouvez pas copier le contenu de la fenêtre Imprimer dans le Presse-papiers (par exemple, avec Ctrl+C). Global ::info écrit dans la fenêtre Infolog qui prend en charge la copie dans le Presse-papiers.
Exemple 1 : Boucle while
Le mot clé while prend en charge la boucle dans X++ et C#.
Exemple X++ de while
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.
}
Output
La sortie de la fenêtre Imprimer X++ est la suivante :
1
2
3
4
Exemple C# de while
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();
}
}
Output
La sortie de la console du programme C# est la suivante :
1
(Press any key to resume.)
2
(Press any key to resume.)
3
(Press any key to resume.)
4
(Press any key to resume.)
Exemple 2 : Boucle for
Le mot clé for prend en charge la boucle dans X++ et C#.
Exemple X++ de for
Dans X++, la variable de compteur ne peut pas être déclarée dans le cadre de l’instruction for .
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;
}
Output
La sortie de la fenêtre Imprimer X++ est la suivante :
1
2
3
4
Exemple C# de for
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();
}
}
Output
La sortie de la console du programme C# est la suivante :
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.)
Comparaison X++, C# : Commutateur
Dans X++ et C#, l’instruction switch implique les mots clés case, break et default. Le tableau suivant répertorie les différences dans l’instruction switch entre X++ et C#.
| Caractéristique | X++ | C# | Commentaires |
|---|---|---|---|
break; à la fin de chaque bloc de cas |
Dans X++, quand un bloc de cas correspond à la valeur d’expression sur la clause switch , tous les autres blocs case et par défaut sont exécutés jusqu’à ce qu’une break; instruction soit atteinte. Aucune instruction n’est break; jamais requise dans une instruction switch X++, mais break; les instructions sont importantes dans presque toutes les situations pratiques. |
En C#, une break; instruction est toujours nécessaire après les instructions dans un bloc case ou par défaut . Si une clause case n’a pas d’instructions entre elle-même et la clause case suivante, une break; instruction n’est pas requise entre les deux clauses case . |
Nous vous recommandons d’omettre l’instruction break; après tout bloc de cas, car il peut confondre le programmeur suivant qui modifie le code. |
break;à la fin du bloc par défaut |
Dans X++, il n’existe aucun effet d’ajout d’une break; instruction à la fin du bloc par défaut . |
En C#, le compilateur nécessite une break; instruction à la fin du bloc par défaut . |
Pour plus d’informations, consultez Instructions Switch. |
| Seules les valeurs constantes d’un bloc de cas | Dans X++, vous pouvez spécifier une valeur littérale ou une variable sur un bloc de casse. Par exemple, vous pouvez écrire la casse myInteger :. | En C#, vous devez spécifier exactement une valeur littérale sur chaque bloc de cas et aucune variable n’est autorisée. | Aucun commentaire. |
| Plusieurs valeurs sur un bloc de cas | Dans X++, vous pouvez spécifier plusieurs valeurs sur chaque bloc de cas. Les valeurs doivent être séparées par une virgule. Par exemple, vous pouvez écrire case 4,5,myInteger:. |
En C#, vous devez spécifier exactement une valeur sur chaque bloc de cas . | Dans X++, il est préférable d’écrire plusieurs valeurs sur un bloc de casse que d’omettre l’instruction break; à la fin d’un ou plusieurs blocs de casse. |
Exemples de code pour le commutateur
Les sections suivantes présentent des instructions switch comparables dans X++ et C#.
Exemple de commutateur X++
L’exemple de commutateur X++ montre les éléments suivants :
-
case iTemp:etcase (93-90):pour montrer que les expressions de cas ne sont pas limitées aux constantes, car elles se trouvent en C#. -
//break;pour montrer que lesbreak;instructions ne sont pas requises dans X++, bien qu’elles soient presque toujours souhaitables. -
case 2, (93-90), 5:pour montrer que plusieurs expressions peuvent être répertoriées sur une clause case dans X++.
static void GXppSwitchJob21(Args _args) // X++ job in AOT > 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
***
Exemple de commutateur C#
L’exemple de commutateur C# montre les éléments suivants :
- case 1 : a un commentaire expliquant que seules les expressions constantes peuvent être données sur une clause case .
-
break;les instructions se produisent après la dernière instruction dans chaque bloc de cas qui a des instructions, comme cela est requis par 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
>>
***/
Comparaison X++, C# : Casse de chaîne et délimiteurs
Cette section compare le traitement des chaînes à la casse mixte en X++ et en C#. Il explique également les délimiteurs de chaînes disponibles dans X++.
Similitudes
Les fonctionnalités X++ suivantes sont les mêmes que dans C# :
- La barre oblique inverse (\) est l’opérateur d’échappement pour les délimiteurs de chaîne.
- Le signe at (@) nullifie l’effet d’échappement de la barre oblique inverse lorsque le signe at est écrit immédiatement avant le guillemet ouvert d’une chaîne.
- Le signe plus (+) est l’opérateur de concaténation de chaîne.
Differences
Les fonctionnalités X++ différentes en C# sont répertoriées dans le tableau suivant.
| Caractéristique | X++ | C# | Commentaires |
|---|---|---|---|
== opérateur de comparaison |
Insensible : l’opérateur == n’est pas sensible aux différences de casse de chaîne. |
En C#, l’opérateur == est sensible aux différences de casse de chaîne. |
Dans X++, vous pouvez utiliser la fonction strCmp pour les comparaisons sensibles à la casse entre les chaînes. |
| Délimiteurs de chaîne | Dans X++, vous pouvez utiliser le guillemet simple (') ou double (") comme délimiteur de chaîne.Note: Généralement, la meilleure pratique consiste à utiliser des guillemets doubles pour les chaînes qui peuvent être affichées à l’utilisateur. Toutefois, il est pratique de délimiter une chaîne avec des guillemets simples lorsqu’un guillemet double est l’un des caractères de la chaîne. |
En C#, vous devez utiliser le guillemet double comme délimiteur de chaîne. Cela fait référence au type System.String. |
Dans X++ et C#, vous avez la possibilité d’incorporer un délimiteur dans une chaîne littérale et de l’échapper avec . Dans X++, vous avez également l’alternative d’incorporer des guillemets simples dans une chaîne délimitée par des guillemets doubles (ou l’inverse), sans avoir à utiliser l’échappement. |
| Délimiteurs de caractères | X++ a un type de données de chaîne (str), mais aucun type de caractère. |
En C#, vous devez utiliser le guillemet unique comme délimiteur de caractères. Cela fait référence au type System.Char. |
Dans .NET Framework, une System.String longueur est un type de données différent d’un System.Char caractère. |
Exemple 1 : Sensibilité de la casse de l’opérateur ==
Les == opérateurs et != ne respectent pas la casse dans X++, mais respectent la casse en C#, comme illustré dans l’exemple suivant.
| X++ | C# | Commentaires |
|---|---|---|
"HELLO" == "hello" True dans X++. |
"HELLO" == "hello" False en C#. |
Comparaisons de cas différentes entre X++ et C#. |
Exemple 2 : Opérateur de concaténation de chaîne +
Les opérateurs + et += sont utilisés pour concaténer des chaînes dans X++ et C#, comme illustré par les exemples du tableau suivant.
| X++ | C# | Commentaires |
|---|---|---|
myString1 = "Hello" + " world"; Résultat : myString1 == "Hello world" |
(Identique à X++.) | Dans X++ et C#, le comportement de l’opérateur + dépend du type de données de ses opérandes. L’opérateur concatène des chaînes ou ajoute des nombres. |
mystring2 = "Hello"; myString2 += " world"; Résultat : myString2 == "Hello world" |
(Identique à X++.) | Dans X++ et C#, les instructions suivantes sont équivalentes : a = a + b; a += b; |
Exemple 3 : Délimiteurs de chaînes incorporés et d’échappement
Les guillemets simples ou doubles peuvent être utilisés pour délimiter des chaînes dans X++. Le caractère d’échappement (\) peut être utilisé pour incorporer des délimiteurs dans une chaîne. Elles sont illustrées dans le tableau suivant.
| X++ | C# | Commentaires |
|---|---|---|
myString1 = "They said \"yes\"."; Résultat: They said "yes". |
(Identique à X++.) | Le caractère d’échappement vous permet d’incorporer des délimiteurs de chaînes à l’intérieur de chaînes. |
myString2 = 'They said "yes".'; Résultat: They said "yes". |
La syntaxe C# n’autorise pas les guillemets simples à délimiter les chaînes. | Pour les chaînes qui peuvent être vues par l’utilisateur, il est considéré comme une bonne pratique d’utiliser le caractère d’échappement au lieu des guillemets simples, comme illustré dans l’exemple. |
myString3 = "They said 'yes'."; Résultat: They said 'yes'. |
(Identique à X++.) | Dans X++, les guillemets simples ne sont pas traités comme des délimiteurs, sauf si la chaîne commence par un séparateur de guillemets unique. En C#, le guillemet unique n’a aucune signification spéciale pour les chaînes et ne peut pas être utilisé pour délimiter les chaînes. En C#, le guillemet unique est le délimiteur requis pour les littéraux de type System.Char. X++ n’a pas de type de données caractère. |
str myString4 = 'C'; Ici, le guillemet unique est un délimiteur de chaîne. |
char myChar4 = 'C'; Ici, le guillemet unique est un System.Char délimiteur, pas un System.String délimiteur. |
X++ n’a aucun type de données correspondant System.Char au .NET Framework. Une chaîne X++ limitée à une longueur d’une chaîne est toujours une chaîne, et non un type de données caractère. |
Exemple 4 : caractère d’échappement unique
Les exemples illustrant le caractère d’échappement unique dans l’entrée ou la sortie sont présentés dans le tableau suivant.
| X++ | C# | Commentaires |
|---|---|---|
myString1 = "Red\ shoe"; Résultat: Red shoe |
Une chaîne littérale en C# ne peut pas contenir la séquence de deux caractères d’échappement suivie d’un espace, tel que « \ ». Une erreur du compilateur se produit. | Lorsque le compilateur X++ rencontre la séquence de deux caractères « \ », elle ignore le caractère d’échappement unique. |
myString2 = "Red\\ shoe"; Résultat: Red\ shoe |
(Identique à X++.) | Dans une paire de caractères d’échappement, le premier annule la signification spéciale de la seconde. |
Comparaison : Syntaxe de tableau
Il existe des similitudes et des différences dans les fonctionnalités et la syntaxe des tableaux dans X++ et C#.
Similitudes
Dans l’ensemble, la syntaxe et le traitement des tableaux sont très similaires dans X++ et C#. Toutefois, il existe de nombreuses différences.
Differences
Le tableau suivant répertorie les zones de la syntaxe [] pour les tableaux qui sont différents pour X++ et C#.
| Catégorie | X++ | C# | Commentaires |
|---|---|---|---|
| Déclaration | Un tableau est déclaré avec des crochets ajoutés au nom de la variable. | Un tableau est déclaré avec des crochets ajoutés au type de données. | int myInts[]; // X++ Note: Un tableau X++ ne peut pas être un paramètre dans une méthode.
|
| Déclaration | La syntaxe de tableau prend uniquement en charge les types de données primitifs, tels que int et str. La syntaxe ne prend pas en charge les classes ou tables. |
La syntaxe de tableau prend en charge les types et classes de données primitifs. | Dans X++, vous pouvez utiliser le Array tableau pour un tableau d’objets. |
| Déclaration | X++ est limité aux tableaux de dimension uniques (myStrings[8]). | C# ajoute la prise en charge des tableaux multidimensionnels (myStrings[8,3]) et des tableaux en jaquet (myStrings[8][3]). | Dans X++, vous ne pouvez pas avoir de tableau de tableaux. Toutefois, il existe une syntaxe avancée pour limiter la quantité de mémoire active qu’un grand tableau peut consommer, ce qui ressemble à la syntaxe multidimensionnelle en C# : int int intarray[1024,16] ;. Pour plus d’informations, consultez Best Practice Performance Optimizations : Swapping Arrays to Disk. |
| Déclaration | Dans X++, un tableau est une construction spéciale, mais ce n’est pas un objet. | En C#, tous les tableaux sont des objets quelles que soient les variantes de syntaxe. | X++ a une classe Array, mais son mécanisme sous-jacent diffère des tableaux créés à l’aide de la syntaxe []. Dans C#, tous les tableaux utilisent le même mécanisme sous-jacent, que la syntaxe [] de la System.Array classe soit utilisée dans votre code. |
| Length | Dans X++, la longueur d’un tableau de taille statique est déterminée dans la syntaxe de déclaration. | En C#, la taille d’un tableau est déterminée lorsque l’objet de tableau est construit. | Lorsque vous utilisez la syntaxe de déclaration [] dans X++, aucune préparation supplémentaire n’est nécessaire avant d’affecter des valeurs au tableau. En C#, vous devez déclarer, puis construire le tableau avant de l’affecter. |
| Length | Un tableau X++ peut avoir une longueur dynamique qui peut être augmentée même après le début de la population. Cela s’applique uniquement lorsque le tableau est déclaré sans nombre à l’intérieur du []. Les performances peuvent être ralenties si la longueur du tableau dynamique est augmentée plusieurs fois. | En C#, la longueur d’un tableau ne peut pas être modifiée une fois la longueur définie. | Dans le fragment de code X++ suivant, seul le myInts tableau est dynamique et peut augmenter la taille. int myInts[]; int myBools[5]; myInts[2] = 12; myInts[3] = 13; myBools[6] = 26; //Error |
| Length | Vous pouvez obtenir la longueur de certains tableaux à l’aide de la dimOf fonction. |
Les tableaux C# sont des objets qui ont une Length propriété. |
Aucun commentaire. |
| Indexation | L’indexation de tableaux est basée sur 1. | L’indexation de tableaux est basée sur 0. | mtIntArray[0] provoquerait une erreur dans X++. |
| Constante | Dans X++, une valeur constante est optimale à l’aide de la directive #define précompiler. | En C#, vous pouvez décorer votre déclaration de variable avec le mot clé const pour obtenir une valeur constante. | X++ n’a aucun mot clé const . C# ne peut pas affecter de valeurs à des variables créées par sa directive #define précompiler. |
Exemples X++ et C#
Les exemples de code suivants montrent comment les tableaux de types de données primitifs sont gérés. Le premier exemple est X++, et le deuxième exemple est en C#. Les deux échantillons obtiennent les mêmes résultats.
Exemple 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]));
}
}
Output
La sortie du journal d’informations est la suivante :
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
Exemple 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
Output
La sortie du programme C# vers la console de ligne de commande est la suivante :
-------- 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]
Fonctionnalités X++ de type tableau supplémentaires
Le conteneur est un type de données spécial disponible dans X++. Elle peut être considérée comme similaire à un tableau ou similaire à une List collection.
Comparaison : Collections
Dans une application finance et opérations, vous pouvez utiliser la classe de collection X++ List . Le .NET Framework utilisé en C# a une classe similaire nommée System.Collections.Generic.List.
Comparaison de l’utilisation des classes de liste
Le tableau suivant compare les méthodes de la classe X++ List aux méthodes sur System.Collections.Generic.List le .NET Framework et C#.
| Caractéristique | X++ | C# | Commentaires |
|---|---|---|---|
| Déclaration de collection | List myList; |
List<string> myList; |
La déclaration X++ n’inclut pas le type d’éléments à stocker. |
| Déclaration d’itérateur | ListIterator iterListEnumerator enumer; |
Iter de chaîne< IEnumerator> ; | Dans X++, l’objet ListIterator a des méthodes qui peuvent insert et delete des éléments à partir de l’objet List. Le X++ ListEnumerator ne peut pas modifier le contenu du List. Dans X++, l’objet ListEnumerator est toujours créé au même niveau que le List. Ce n’est pas toujours vrai pour ListIterator. |
| Obtention d’un itérateur | new ListIterator (myList)myList.getEnumerator() |
myList.GetEnumerator() |
Dans X++ et C#, l’objet List a une méthode getter pour un énumérateur associé. |
| Constructeur | new List(Types::String) |
new List<string>() |
Les informations sur le type d’objets à stocker à l’intérieur des List classes sont fournies au constructeur dans X++ et C#. |
| Mise à jour des données | Énumérateur : l’énumérateur devient non valide si des éléments du List fichier sont ajoutés ou supprimés.Itérateur : l’itérateur a des méthodes qui insèrent et suppriment des éléments du List. L’itérateur reste valide. |
Énumérateur : l’énumérateur devient non valide si des éléments du List fichier sont ajoutés ou supprimés. |
Les énumérateurs deviennent non valides une fois les éléments ajoutés ou supprimés du List, dans X++ et C#. |
| Mise à jour des données | Dans X++, la List classe a des méthodes pour ajouter des éléments au début ou à la fin de la liste. |
En C#, la List classe a des méthodes pour ajouter des membres à n’importe quelle position dans la liste. Il a également des méthodes pour supprimer des éléments de n’importe quelle position. |
Dans les éléments X++, vous pouvez supprimer des éléments uniquement List par un itérateur. |
Exemple 1 : Déclaration d’une liste
Les exemples de code suivants sont dans X++ et C# qui déclarent List des collections.
// X++
List listStrings ,list2 ,listMerged;
ListIterator literator;
// C#
using System;
using System.Collections.Generic;
List<string> listStrings ,list2 ,listMerged; IEnumerator<string> literator;
Exemple 2 : Construction d’une liste
Dans les deux langues, le type d’éléments que la collection stocke doit être spécifié au moment de la construction. Pour les types de classes, X++ ne peut pas obtenir plus spécifique que si le type est une classe (Types ::Class). Les exemples de code suivants sont dans X++ et C#.
// X++
listStrings = new List( Types::String );
// C#
listStrings = new List<string>;
Exemple 3 : Ajouter des éléments à une liste
Dans X++ et C#, la collection fournit une méthode permettant d’ajouter un élément à la fin de la collection et d’insérer un élément au début. En C#, la collection fournit une méthode d’insertion à n’importe quel point de la collection en fonction d’une valeur d’index. Dans X++, un itérateur de collection peut insérer un élément à sa position actuelle. Les exemples de code suivants sont dans X++ et 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");
Exemple 4 : Itérer dans une liste
X++ et C# ont des classes d’itérateur que vous pouvez utiliser pour parcourir les éléments d’une collection, comme illustré dans les exemples suivants.
// 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);
}
Exemple 4b : foreach en C#
En C#, le mot clé foreach est souvent utilisé pour simplifier la tâche d’itération dans une liste. L’exemple de code suivant se comporte de la même façon que l’exemple C# précédent.
foreach (string currentString in listStrings)
{
Console.WriteLine(currentString);
}
Exemple 5 : Supprimer le deuxième élément
Les exemples de code suivants suppriment le deuxième élément de la collection. Dans X++, cela nécessite un itérateur. En C# la collection elle-même fournit la méthode de suppression d’un élément.
// X++
literator.begin();
literator.next();
literator.delete();
// C#
listStrings.RemoveAt(1);
Exemple 6 : Combiner deux collections
Les exemples de code suivants combinent le contenu de deux collections en un seul.
// X++
listStrings = List::merge(listStrings ,listStr3);
// Or use the .appendList method:
listStrings.appendList (listStr3);
// C#
listStrings.InsertRange(listStrings.Count ,listStr3);
Comparaison : Collections de clés avec des valeurs
Dans une application finance et opérations, vous pouvez utiliser la classe de Map collection. La Map collection contient des paires de valeurs, la valeur de clé et une valeur de données. Cela ressemble à la classe .NET Framework nommée System.Collections.Generic.Dictionary.
Similitudes
La liste suivante décrit les similitudes entre X++ et C# concernant leurs collections qui stockent des paires clé-valeur :
- Les deux empêchent les clés dupliquées.
- Les deux utilisent un énumérateur (ou itérateur) pour parcourir les éléments.
- Les deux objets de collection clé-valeur sont construits avec des désignations des types stockés en tant que clé et valeur.
- Les deux peuvent stocker des objets de classe et ne sont pas limités au stockage de primitives comme int.
Differences
Le tableau suivant décrit les différences entre X++ et C# concernant leurs classes de collections qui stockent des paires clé-valeur :
| Caractéristique | X++ | C# | Commentaires |
|---|---|---|---|
| Clés dupliquées | Dans X++, la Map classe empêche les clés en double en traitant implicitement votre appel à sa insert méthode comme une opération pour mettre à jour uniquement la valeur associée à la clé. |
En C#, la Dictionary classe lève une exception lorsque vous essayez d’ajouter une clé en double. |
Les clés en double sont empêchées dans les deux langages, bien que par différentes techniques. |
| Supprimer des éléments | Dans X++, la delete méthode sur un objet itérateur est utilisée pour supprimer une paire clé-valeur indésirable d’un Map. |
En C#, la Dictionary classe a une remove méthode. |
Dans les deux langues, un énumérateur n’est pas valide si le nombre d’éléments de collection est modifié pendant la durée de vie de l’énumérateur. |
Exemple 1 : Déclaration d’une collection Key-Value
Dans les deux langues, le type d’éléments que la collection clé-valeur stocke doit être spécifié. Dans X++, le type est spécifié au moment de la construction. En C#, le type est spécifié à la fois au moment de la déclaration et de l’heure de construction. Les exemples de code suivants sont dans X++ et C#.
// X++
Map mapKeyValue;
MapEnumerator enumer;
MapIterator mapIter;
// C#
Dictionary<int,string> dictKeyValue;
IEnumerator<SysCollGen.KeyValuePair<int,string>> enumer;
KeyValuePair<int,string> kvpCurrentKeyValuePair;
Exemple 2 : Construction de la collection
Dans les deux langages, le type d’éléments que la collection clé-valeur stocke spécifié lors de la construction. Pour les types de classes, X++ ne peut pas obtenir plus spécifique que si le type est une classe (Types ::Class). Les exemples de code suivants sont dans X++ et C#.
// X++
mapKeyValue = new Map(Types::Integer, Types::String);
// C#
dictKeyValue = new Dictionary<int,string>();
Exemple 3 : Ajouter un élément à la collection
Il n’existe presque aucune différence dans la façon dont un élément est ajouté à une collection clé-valeur dans X++ et C#, comme illustré dans les exemples de code suivants.
// X++
mapKeyValue.insert(xx ,int2str(xx) + “_Value”);
// C#
dictKeyValue.Add(xx ,xx.ToString() + “_Value”);
Exemple 4 : Itérer au sein d’une collection Key-Value
Les énumérateurs sont utilisés pour parcourir les collections clé-valeur dans X++ et C#, comme illustré dans les exemples de code suivants.
// 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.
}
Exemple 5 : Mettre à jour la valeur associée à une clé
La syntaxe est très différente entre les deux langues pour une mise à jour de la valeur associée à une clé donnée. Les exemples de code ollowing concernent la clé 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.”;
Exemple 6 : Supprimer un élément
La syntaxe est très différente entre les deux langages pour supprimer une paire clé-valeur d’une collection, tout en itérant dans les membres de la collection. Les exemples de code de la clé 102 sont présentés ci-dessous.
// 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);
Comparaison : Exceptions
Il existe des similitudes, mais de nombreuses différences s’affichent lorsque nous comparons le comportement lié aux exceptions entre X++ et C#. Les mots clés try, catch et throw se comportent de la même façon dans X++ et C#. Toutefois, les types d’exceptions levées et interceptées sont différents pour les deux langues.
Similitudes
Les similitudes entre X++ et C# concernant leurs fonctionnalités d’exception incluent les exemples suivants :
- Les deux langues ont le même mot clé try .
- Les deux ont le même mot clé catch .
- Activez les deux pour une instruction catch qui ne spécifie aucune exception particulière. Une telle instruction catch intercepte toutes les exceptions qui l’atteignent.
- Les deux ont le même mot clé de levée .
Differences
Les différences liées aux exceptions entre X++ et C# sont décrites dans le tableau suivant.
| Caractéristique | X++ | C# | Commentaires |
|---|---|---|---|
| réessayer | Passe à la première instruction du bloc try associé. Pour plus d’informations, consultez Gestion des exceptions avec try and catch Keywords. | Les fonctionnalités du mot clé de nouvelle tentative peuvent être imitées dans le code C#, mais il n’existe pas de mot clé correspondant. | Seul X++ a un mot clé de nouvelle tentative . C# n’a pas d’équivalent. Pour plus d’informations, consultez Comparaison X++, C# : Nouvelle tentative automatisée après une exception. |
| finalement | Le finally mot clé est pris en charge pour suivre les mots clés et try les catch mots clés. |
Le mot clé final marque un bloc de code qui suit les blocs try et catch . La dernière est exécutée, que l’exception soit levée ou interceptée. | La sémantique est identique à la sémantique en C#. |
| Exceptions spécifiques | Dans X++, une exception est un élément de l’énumération Exception , tel que Error, Deadlock ou CodeAccessSecurity. Aucune exception ne peut contenir une autre. |
En C#, une exception est une instance de la System.Exception classe de base, ou toute classe qui hérite de celle-ci. Une exception peut être contenue dans la InnerException propriété de l’exception levée. |
Dans X++, chaque exception levée est une valeur de l’énumération d’exception. Pour plus d’informations, consultez Énumération d’exception. |
| Message d’exception | Dans X++, le message créé lorsqu’une exception est levée est disponible uniquement dans le journal des informations et le message n’est pas directement lié à l’exception. | En C#, le message est le Message membre de l’objet System.Exception . |
Dans X++ la méthode Global ::error est le mécanisme qui affiche les messages d’exception dans le journal d’informations. Pour plus d’informations, consultez Gestion des exceptions avec try and catch Keywords. |
| Conditions d’exception | Dans X++, une erreur se produit lorsque vous appelez une méthode d’instance sur une variable objet qui n’a pas encore été affectée à celle-ci. Toutefois, aucune exception n’est levée avec cette erreur. Par conséquent, aucun bloc ne catch peut obtenir le contrôle même si la variable non attribuée est utilisée de manière incorrecte dans un try bloc. Dans l’exemple de code suivant, l’erreur provoquée par le code box4.toString(); n’entraîne pas le transfert du contrôle vers un catch bloc : DialogBox box4;try { } box4.toString(); info("toString did not error, but expected an error."); catch (Exception ::Error) // Aucune valeur d’exception intercepte ceci. { info("Invalid use of box4 gave control to catch, unexpected."); } |
En C# a System.NullReferenceException été déclenché lorsqu’une variable non initialisée est traitée comme une référence d’objet. |
Il peut y avoir plusieurs autres différences dans les conditions qui déclenchent des exceptions. |
| Transactions SQL | Dans X++ lorsqu’une exception SQL se produit dans une transaction ttsBegin - ttsCommit , aucune instruction catch dans le bloc de transaction ne peut traiter l’exception. | En C#, un bloc catch à l’intérieur d’une transaction SQL peut intercepter l’exception. |
Examples
Les fonctionnalités X++ suivantes sont illustrées :
- essayez le mot clé.
- mot clé catch .
- Comportement après une exception Exception ::Error se produit.
Exemple 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.");
}
Output
Voici la sortie de la fenêtre 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.
Exemple C#
Le programme C# suivant est une réécriture du programme X++ précédent.
// 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
Output
Voici la sortie de la console C# :
(e2) In catch block for -- System.IndexOutOfRangeException
'finally' is not an X++ keyword, although it's in C#.
End of program.
Comparaison : Nouvelle tentative automatisée après une exception
Parfois, vous pouvez écrire du code dans un bloc catch qui corrige la cause d’une exception qui se produit pendant l’exécution. X++ fournit un mot clé de nouvelle tentative qui peut être utilisé uniquement à l’intérieur d’un bloc catch . Le mot clé de nouvelle tentative permet à un programme de revenir au début du bloc try une fois que le problème a été corrigé par le code dans le bloc catch . C# n’a pas de mot clé de nouvelle tentative . Toutefois, le code C# peut être écrit pour fournir un comportement équivalent.
Exemples de code pour réessayer
L’exemple de programme X++ suivant déclenche une exception ::Error. Cela se produit lorsqu’il tente d’abord de lire un élément à partir du tableau à l’aide sStrings d’une valeur d’index non valide. Lorsque l’exception est interceptée, une action corrective est effectuée pendant l’exécution à l’intérieur du bloc catch . L’instruction de nouvelle tentative revient ensuite à la première instruction du bloc try . Cette deuxième itération fonctionne sans rencontrer d’exception.
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;
}
Output
Voici la sortie de la fenêtre Imprimer :
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.
Exemple C#
L’exemple C# suivant n’est pas une traduction ligne par ligne de l’exemple X++ précédent. Au lieu de cela, le programme C# a une structure différente pour qu’il imite le comportement du mot clé de nouvelle tentative sur lequel repose le programme X++. Les blocs try et catch se trouvent dans une méthode appelée. Les variables utilisées dans le bloc try sont stockées dans la méthode de l’appelant. La méthode appelant transmet les variables en tant que paramètres décorés avec le mot clé ref , afin que leurs valeurs puissent être corrigées à l’intérieur du bloc catch de la méthode appelée. La méthode appelée capture toutes les exceptions et retourne une valeur booléenne pour communiquer avec l’appelant si un deuxième appel est requis.
// 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;
}
}
Output
Voici la sortie de la console :
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.
Comparaison : opérateurs
Cette section compare les opérateurs entre X++ et C#.
Opérateurs d’affectation
Le tableau suivant affiche les différences entre les opérateurs d’affectation dans X++ et C#.
| X++ et C# | Differences |
|---|---|
= |
Dans X++, cet opérateur provoque une conversion implicite chaque fois qu’une perte de précision peut se produire, par exemple pour une affectation d’un int64 en int. Toutefois, en C#, l’affectation provoque une erreur de compilation. |
+= et -= |
La seule différence est que dans C# ces opérateurs sont également utilisés dans la manipulation de délégués. |
| ++ et -- | Il s’agit des opérateurs d’incrémentation et de décrémentation dans les deux langues. La ligne suivante est identique dans les deux langues :++myInteger;Toutefois, dans X++, ces deux opérateurs concernent les instructions, et non pour les expressions. Par conséquent, les lignes suivantes génèrent des erreurs de compilation dans X++ : myStr = int2str(++myInteger);myIntA = myIntBB++; |
Opérateurs arithmétiques
Le tableau suivant répertorie les opérateurs arithmétiques :
| X++ et C# | Differences |
|---|---|
| * | En tant qu’opérateur de multiplication, il n’y a aucune différence. Note: L’astérisque est également utilisé dans les instructions SQL qui font partie du langage X++. Dans ces instructions SQL, l’astérisque peut également être l’un des éléments suivants :
|
/ |
L’opérateur de division est le même dans X++ et C#. |
MOD |
Pour les opérations modulo, la seule différence est que le symbole % est utilisé en C#. |
| + | L’opérateur d’ajout est le même dans X++ et C#. Le signe plus est également utilisé pour la concaténation de chaînes. Cet opérateur ajoute des nombres et concatène des chaînes dans les deux langues. |
| - | L’opérateur de soustraction est identique dans X++ et C#. |
Opérateurs au niveau du bit
Le tableau suivant compare les opérateurs au niveau du bit entre X++ et C#.
| X++ et C# | Differences |
|---|---|
| << | L’opérateur de décalage gauche est le même en X++ et en C#. |
| >> | L’opérateur de décalage droit est le même en X++ et en C#. |
| ~ | L’opérateur NOT au niveau du bit est le même dans X++ et C#. |
| & | L’opérateur AND binaire est identique dans X++ et C#. |
| ^ | L’opérateur XOR binaire est le même dans X++ et C#. |
Opérateurs relationnels
Les opérateurs relationnels suivants sont identiques dans X++ et C# :
==<=<=><!=&&||!? :
Comparaison : événements
Il existe des différences dans la façon dont X++ et C# implémentent le modèle de conception d’événements. Pour plus d’informations, consultez terminologie et mots clés des événements.
Comparaison des événements entre X++ et C#
Il existe des différences dans la façon dont les délégués sont utilisés pour les événements dans X++ et C#.
| Concept | X++ | C# | Commentaires |
|---|---|---|---|
| delegate | Dans X++, un délégué peut être déclaré uniquement en tant que membre d’une classe. Un délégué ne peut pas être membre d’une table. Tous les délégués sont des membres d’instance de leur classe, et non des membres statiques . Aucun modificateur d’accès ne peut être utilisé sur une déclaration de délégué, car tous les délégués sont des membres protégés . Par conséquent, l’événement ne peut être déclenché que par du code dans la même classe où le délégué est membre. Toutefois, l’une des exceptions à la nature privée d’un délégué est que le code en dehors de leur classe peut fonctionner sur les délégués à l’aide des opérateurs += et -=. | En C#, chaque délégué est un type, tout comme chaque classe est un type. Un délégué est déclaré indépendamment de n’importe quelle classe. Sans le mot clé d’événement , vous pouvez avoir un délégué en tant que type de paramètre sur une méthode, tout comme vous pouvez avoir une classe comme type de paramètre. Vous pouvez construire une instance d’un délégué à transmettre pour la valeur du paramètre. | Dans X++, chaque classe est un type, mais aucun délégué n’est un type. Vous ne pouvez pas construire une instance d’un délégué. Aucun délégué ne peut être un paramètre pour une méthode. Toutefois, vous pouvez créer une classe qui a un membre délégué et passer des instances de la classe en tant que valeurs de paramètre. Pour plus d’informations, consultez mots clés X++. |
| événement | Dans le code X++, un événement est l’un des éléments suivants :
|
En C#, le mot clé d’événement est utilisé pour déclarer un type délégué en tant que membre d’une classe. L’effet du mot clé d’événement est de rendre le délégué protégé, mais toujours accessible pour les opérateurs += et -=. Vous pouvez abonner des méthodes de gestionnaire d’événements à un événement à l’aide de l’opérateur += . Un délégué peut être utile sans le mot clé d’événement , comme technique pour transmettre un pointeur de fonction en tant que paramètre à une méthode. | Les événements automatiques qui se produisent avant le début d’une méthode, et après la fin d’une méthode, peuvent être abonnés uniquement à l’aide de l’AOT. |
| += et -= opérateurs | Dans X++, vous utilisez l’opérateur += pour abonner des méthodes à un délégué. L’opérateur -= désinscrit une méthode d’un délégué. | En C#, vous utilisez l’opérateur += pour abonner des méthodes à un événement ou à un délégué qui n’est pas utilisé avec le mot clé d’événement . | Le délégué contient une référence à tous les objets auxquels les méthodes sont abonnées au délégué. Ces objets ne sont pas éligibles pour le garbage collection pendant que le délégué contient ces références. |
eventHandler |
Dans X++, le mot clé eventHandler est requis lorsque vous utilisez l’opérateur += ou -= pour s’abonner ou désabonner une méthode d’un délégué. |
System.EventHandler est un type délégué dans le .NET Framework. |
Ce terme est utilisé différemment dans X++ que dans C# ou .NET Framework. Pour plus d’informations, consultez mots clés X++. |
Exemple X++
Les points importants à noter sont les suivants dans l’exemple X++ :
Le
XppClassmembre délégué est nommémyDelegate.Note
L’AOT contient un nœud pour le délégué. Le nœud se trouve dans les classes > AOT > XppClass > myDelegate. Plusieurs nœuds de gestionnaire d’événements peuvent se trouver sous le nœud myDelegate. Les gestionnaires d’événements représentés par des nœuds dans l’AOT ne peuvent pas être supprimés par l’opérateur -= pendant l’exécution.
Les {} accolades à la fin de la déclaration de délégué sont requises, mais elles ne peuvent pas contenir de code.
Il
XppClassexiste deux méthodes dont les signatures de paramètre sont compatibles avec le délégué. Une méthode est statique.Les deux méthodes compatibles sont ajoutées au délégué avec l’opérateur += et le mot clé eventHandler . Ces instructions n’appellent pas les méthodes du gestionnaire d’événements, les instructions ajoutent uniquement les méthodes au délégué.
L’événement est déclenché par un appel au délégué.
La valeur du paramètre transmise au délégué est reçue par chaque méthode de gestionnaire d’événements.
Le travail X++ court en haut de l’exemple démarre le test.
// 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);
}
}
La sortie du travail X++ précédent est la suivante :
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.
Exemple C#
Cette section contient un exemple de code C# pour le modèle de conception d’événements de l’exemple X++ précédent.
// 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);
}
}
La sortie de l’exemple C# précédent est la suivante :
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.
Événements et AOT
Il existe d’autres systèmes d’événements qui s’appliquent uniquement aux éléments de l’AOT. Pour plus d’informations, consultez Nœuds du gestionnaire d’événements dans aOT.
Comparaison : Directives de précompiler
X++ et C# partagent certains mots clés pour leur syntaxe de directive précompiler, mais les significations ne sont pas toujours les mêmes.
Similitudes
Les compilateurs X++ et C# reconnaissent la plupart des mêmes mots clés. Dans la plupart des cas, les mots clés signifient les mêmes pour les deux compilateurs de langage.
Differences
Une différence fondamentale entre les directives de précompileur dans X++ et C# est le mot clé #define que les précompileurs de langage reconnaissent. Contrairement à C#, dans X++, la directive #define nécessite un point dans sa syntaxe. Dans X++, les parenthèses peuvent être utilisées pour donner au symbole défini une valeur. Ces différences sont présentées dans les exemples suivants :
- Dans X++ : #define. InitialYear(2003)
- En C# : #define InitialYear
Une différence mineure est que dans C# il peut y avoir des espaces et des caractères de tabulation entre le caractère # et le mot clé de directive, tel que # define Testing.
Mots clés identiques
Le tableau suivant répertorie les directives de précompileur similaires dans X++ et C#.
| Keyword | X++ | C# | Commentaires |
|---|---|---|---|
#define |
Dans X++, un nom de variable précompileur peut être défini et une valeur peut être donnée à cette variable. | En C#, un nom de variable précompileur peut être défini, mais aucune valeur ne peut être donnée à cette variable. En outre, toute #define en C# doit se produire en haut du fichier et ne peut pas se produire après tout code tel qu’une instruction using ou une déclaration de classe. | Le compilateur C# peut entrer un paramètre de ligne de commande pour définir un nom de /define variable précompileur sans définir la variable dans un fichier de code C#. Le compilateur X++ n’a pas d’équivalent à /define. |
#if |
Dans X++, #if pouvez déterminer si une variable de précompileur existe et si la variable a une valeur donnée. | En C#, #if ne peut déterminer si une variable de précompileur existe. Il ne peut pas tester de valeur, car aucune valeur ne peut être affectée. | |
#endif |
Dans X++, #endif marque la fin d’un bloc #if. Il met également fin à un bloc #ifnot. | En C#, #endif marque la fin d’un bloc #if, que le bloc contienne un #else. |
Mots clés différents avec le même résultat de traitement
Le tableau suivant répertorie les directives de précompiler nommées différemment dans X++ et C#, mais qui donnent les mêmes résultats lors du traitement.
| X++ | C# | Commentaires |
|---|---|---|
| #ifnot | #if #else | Il n’existe pas de directive #else dans X++, mais la #ifnot fournit des fonctionnalités similaires. Dans X++, #ifnot pouvez déterminer si une variable de précompileur existe et si la variable n’a pas de valeur donnée spécifique. En C#, #if pouvez déterminer si une variable de précompileur existe lorsque le « ! » le symbole est préfixé au nom de la variable. |
//BP Deviation documented |
avertissement #pragma | Ces entrées X++ et C# ne sont pas équivalentes, mais il existe une similitude partielle. Les deux suppriment les messages d’avertissement du compilateur. |
| #macrolib | . Fichier HPP en C++ | Il existe une similarité partielle entre la directive X++ #macrolib par rapport à une . Fichier HPP en C++. Les deux peuvent contenir plusieurs instructions #define. |
Directives de précompiler exclusives à X++
Le tableau suivant répertorie les directives de précompileur X++ qui n’ont aucun équivalent direct en C#.
| X++ | Commentaires |
|---|---|
| #linenumber | La directive #linenumber consiste à obtenir le numéro de ligne afin qu’il puisse être généré dans le journal d’informations. La directive C# #line est différente, car son objectif est de définir le numéro de ligne. |
| #defdec #definc | |
| #globaldefine | Dans X++, il existe une petite différence entre #globaldefine et #define. La différence est que #globaldefine ne remplace jamais une valeur non nulle actuelle qui a été affectée à une variable de précompileur par #define. C# n’a rien de similaire à cette différence, car en C#, un nom de variable précompileur ne peut pas être attribué à une valeur. |
| #localmacro #macro | Dans X++, #localmacro vous permet d’affecter une valeur multiligne à une variable précompileur. #macro est un synonyme, mais #localmacro est recommandé. En C#, la directive #define fait partie de cette fonctionnalité, mais elle ne peut pas affecter de valeur à une variable de précompileur. |
| #globalmacro | Dans X++, #globalmacro est presque identique à la #localmacro préférée. |
Comparaison : Programmation orientée objet
Les principes de programmation orientée objet (OOP) de X++ diffèrent de C#.
Comparaisons conceptuelles
Le tableau suivant compare l’implémentation des principes OOP entre X++ et C#.
| Caractéristique | X++ | C# | Commentaires |
|---|---|---|---|
| Sélection des acteurs | Le langage X++ a les mots clés etcomme, qui sont utilisés pour rendre les downcasts sécurisés et explicites. Conseil : X++ ne nécessite pas l’utilisation du mot clé lorsque vous avez bascasté une variable de classe de base sur une variable de classe dérivée. Toutefois, nous recommandons que toutes les instructions de downcast utilisent le mot clé. | Un objet peut être casté vers le haut ou vers le bas du chemin d’héritage. Les downcasts nécessitent le mot clé. | Pour plus d’informations sur les mots clés X++, consultez Opérateurs d’expression : Is and As for Inheritance. |
| Fonctions locales | Une méthode peut contenir une déclaration et un corps de code pour zéro ou plusieurs fonctions locales. Seule cette méthode peut avoir des appels à la fonction locale. | C# 3.0 prend en charge les expressions lambda, qui ont une certaine similarité avec les fonctions anonymes et les fonctions locales. Les expressions lambda sont souvent utilisées avec des délégués. | |
| Surcharge de méthode | La surcharge de méthode n’est pas prise en charge. Un nom de méthode ne peut se produire qu’une seule fois par classe. | La surcharge de méthode est prise en charge. Un nom de méthode peut se produire plusieurs fois dans une classe, avec des signatures de paramètres différentes dans chaque cas. | X++ prend en charge les paramètres facultatifs sur les méthodes. Les paramètres facultatifs peuvent imiter partiellement la surcharge de méthode. Pour plus d’informations, consultez la ligne des paramètres facultatifs dans ce tableau. |
| Substitution de méthode | La substitution de méthode est prise en charge. Une classe dérivée peut avoir une méthode du même nom que dans la classe de base, tant que la signature du paramètre est identique dans les deux cas. La seule exception est que la méthode de substitution peut ajouter une valeur par défaut à un paramètre. | La substitution de méthode est prise en charge. Le mot clé virtuel doit être appliqué à une méthode avant que la méthode puisse être substituée dans une classe dérivée. | Le concept de substitution d’une méthode inclut le nom de la méthode, sa signature de paramètre et son type de retour. Le concept de substitution de méthode ne s’applique pas si la méthode de base et la méthode de substitution diffèrent dans l’un de ces aspects. |
| Paramètres facultatifs | Une déclaration de paramètre peut être suivie d’une affectation de valeur par défaut. L’appelant de méthode a la possibilité de transmettre une valeur pour ce paramètre ou d’ignorer le paramètre pour accepter la valeur par défaut. Cette fonctionnalité imite la surcharge des méthodes, car deux appels au même nom de méthode peuvent passer différents nombres de paramètres. Chaque paramètre qui a une valeur par défaut doit suivre le dernier paramètre qui n’a pas de valeur par défaut. | Les paramètres facultatifs sont pris en charge par le mot clé params . Même sans le mot clé params , du point de vue de l’appelant, la surcharge de méthode peut fournir des fonctionnalités partiellement similaires. | Pour plus d’informations, consultez Paramètres et étendues et Utilisation des paramètres facultatifs. |
| Héritage unique | Vous pouvez dériver votre classe X++ d’une autre classe X++ à l’aide du mot clé extends dans le nœud classDeclaration de votre classe, dans l’AOT. Aucune classe dérive implicitement d’une autre classe. Si vous souhaitez que votre classe dérive directement de la Object classe, vous devez utiliser le mot clé extends . Vous ne pouvez spécifier qu’une seule classe sur le mot clé extends .Attention : lorsque vous modifiez une classe de base X++ à partir de laquelle d’autres classes dérivent, vous devez recompiler cette classe de base à l’aide de Compile forward. Cette option garantit que les classes dérivées sont également recompilées. Pour vous assurer que les classes dérivées sont également recompilées, cliquez avec le bouton droit sur le nœud de classe de base, puis cliquez sur Add-Ins > Compiler vers l’avant. L’alternative de cliquer sur Build > Compile (ou d’appuyer sur la touche F7) est parfois insuffisante pour une modification de classe de base. Une classe peut implémenter zéro pour de nombreuses interfaces. Une table X++ hérite implicitement de la Common table et de la xRecord classe. |
C# utilise le mot clé extends pour dériver d’une autre classe. Toutes les classes .NET Framework dérivent implicitement de la System.Object classe, sauf si elles dérivent explicitement d’une autre classe. |
Comparaisons de mots clés
Le tableau suivant répertorie les mots clés liés à l’OOP dans X++ et C#.
| Keyword | X++ | C# | Commentaires |
|---|---|---|---|
| abstract | Pas de différence. | ||
| classe | Les modificateurs publics et privés sont ignorés sur les déclarations de classe. Il n’existe pas de concept de regroupement d’espaces de noms de classes. Il n’y a aucun point (.) dans les noms de classes. | Les modificateurs publics et privés peuvent être utilisés pour modifier les déclarations de classe. C# a également le mot clé interne, qui concerne la façon dont les classes sont regroupées dans les fichiers d’assembly. | Il n’existe pas de concept de classe protégée , seuls les membres protégés d’une classe. |
| S' étend | Une déclaration de classe peut hériter d’une autre classe à l’aide du mot clé extends . | Un signe deux-points (:) est utilisé où les mots clés s’étendent et implémentent sont utilisés dans X++. | |
| final | Une méthode finale ne peut pas être substituée dans une classe dérivée. Une classe finale ne peut pas être étendue. | Le mot clé scellé sur une classe signifie la même chose que la dernière signifie sur une classe X++. | |
| Implémente | Une déclaration de classe peut implémenter une interface à l’aide du mot clé implémente . | ||
| interface | Une interface peut spécifier des méthodes que la classe doit implémenter. | Une interface peut spécifier des méthodes que la classe doit implémenter. | |
| Nouveau | Le nouveau mot clé est utilisé pour allouer une nouvelle instance d’une classe. Ensuite, le constructeur est automatiquement appelé. Chaque classe a exactement un constructeur et le constructeur est nommé new. Vous pouvez décider des paramètres que le constructeur doit entrer. |
Le nouveau mot clé est utilisé pour créer une instance d’une classe. Ensuite, le constructeur est automatiquement appelé. Les méthodes de constructeur elles-mêmes ne sont pas nommées new, elles ont le même nom que la classe.Note: Le nouveau mot clé peut également être utilisé sur une méthode pour modifier la façon dont la méthode remplace la même méthode dans la classe de base. |
X++ et C# supposent un constructeur par défaut pour les classes qui n’ont aucun constructeur explicitement écrit dans leur code. |
| zéro | Pas de différence. | ||
| privé et protégé | Les mots clés privés et protégés peuvent être utilisés pour modifier la déclaration d’un membre de classe. | Les mots clés privés et protégés peuvent être utilisés pour modifier la déclaration d’un membre de classe. | |
| public | Une méthode qui n’est pas modifiée avec public, protégé ou privé a le niveau d’accès par défaut public. | Une méthode qui n’est pas modifiée avec public, protégé ou privé a le niveau d’accès privé par défaut. | |
| statique | Une méthode peut être statique, mais un champ ne peut pas. | Les deux méthodes et champs peuvent être statiques. | |
| super | Le super mot clé est utilisé dans une classe dérivée pour accéder à la même méthode sur sa classe de base. void method2(){ // Call method2 method // on the base class. super(); } |
Le mot clé de base est utilisé dans une classe dérivée pour accéder à différentes méthodes dans sa classe de base. void method2() { // Call methods on // the base class. base.method2(); base.method3(); } |
En C#, il existe une syntaxe spéciale pour utiliser la base pour appeler le constructeur de base. |
| ceci | Pour un appel d’une méthode d’instance à un autre sur le même objet, un qualificateur pour la méthode appelée est requis. Mot clé disponible en tant que qualificateur pour l’objet actuel. | Pour un appel d’une méthode d’instance à un autre sur le même objet, un qualificateur pour la méthode appelée n’est pas obligatoire. Toutefois, ce mot clé est disponible en tant que qualificateur pour l’objet actuel. Dans la pratique, le mot clé peut être utile en affichant des informations IntelliSense. | |
finalize |
La Object classe contient la finalize méthode. La finalize méthode n’est pas finale et peut être remplacée. La finalize méthode semble ressembler à la System.Object.Finalize méthode en C#, mais dans X++, la finalize méthode n’a aucune signification particulière. Un objet est automatiquement supprimé de la mémoire lorsque la dernière référence à l’objet cesse de référencer l’objet. Par exemple, cela peut se produire lorsque la dernière référence sort de l’étendue ou est affectée à un autre objet à référencer. |
Les méthodes Finalize et Dispose sont courantes sur certains types de classes. Le garbage collector appelle les méthodes et Finalize les Dispose méthodes lorsqu’il détruit et objet. |
En C#, la System.GC.Collect méthode du .NET Framework peut être appelée pour démarrer le garbage collector. Il n’existe pas de fonction similaire dans X++, car X++ utilise un garbage collector déterministe. |
main |
Les classes appelées à partir d’un menu ont leur main méthode appelée par le système. |
Les classes appelées à partir d’une console de ligne de commande ont leur Main méthode appelée par le système. |
Comparaison : classes
Lorsque vous utilisez C# dans .NET Framework, les classes sont regroupées en espaces de noms. Chaque espace de noms se concentre sur une zone fonctionnelle telle que les opérations de fichier ou la réflexion. Toutefois, lorsque vous utilisez les classes dans X++, il n’existe aucun regroupement visible comme un espace de noms.
Comparaison : Classes sur la réflexion
Dans X++, la TreeNode classe fournit l’accès à l’arborescence d’objets d’application (AOT). La TreeNode classe est le centre de la fonctionnalité de réflexion dans X++. La TreeNode classe et ses méthodes peuvent être comparées à l’espace System.Reflection de noms dans le .NET Framework que C# utilise.
Le tableau suivant répertorie plusieurs classes disponibles lorsque vous écrivez du code C#. Il s’agit de classes .NET Framework. Pour cette table, toutes les classes C# se trouvent dans l’espace System.Reflection de noms, sauf indication contraire. Chaque ligne affiche la classe correspondante, ou membre de classe, qui est disponible lorsque votre code X++ écrit.
| X++ | C# | Commentaires |
|---|---|---|
TreeNode |
System .Assembly |
L’assembly est la première classe à utiliser lorsqu’un programme C# doit collecter des informations de réflexion. Les méthodes statiques sur la classe TreeNode X++ sont le point de départ de la réflexion dans X++. |
TreeNode |
System .Type |
Les méthodes d’instance sur TreeNode correspondent aux méthodes d’instance sur System.Type. |
TreeNode .AOTgetSource |
MethodInfo |
La AOTgetSource méthode retourne plusieurs informations ensemble dans une chaîne. Cela inclut le code source X++ dans la méthode. En revanche, MethodInfo a un membre distinct pour chaque élément d’information. |
TreeNode .AOTfirstChild
TreeNode .AOTnextSibling
TreeNode .AOTiterator
AOTiterator
|
MethodInfo[] (tableau) | En C#, la GetMethods méthode sur System.Type retourne un tableau d’objets MethodInfo. Vous pouvez parcourir le tableau par la technique courante d’incrémentation d’un indexeur. En revanche, le modèle X++ consiste à naviguer dans l’arborescence du contrôle AOT. Méthodes TreeNode de AOTfirstChild navigation et AOTnextSibling réalisation de la navigation. En guise d’alternative équivalente, la classe X++ AOTiterator est conçue pour naviguer dans l’arborescence du contrôle AOT. Un nœud de classe est le parent sur plusieurs nœuds de méthode. Les AOTiterator étapes par le biais des nœuds enfants, en retournant chacune sous la forme d’une autre TreeNode instance. Ressources supplémentaires les TreeNode méthodes nommées AOTparent et AOTprevious. |
TreeNode .AOTgetProperty
TreeNode .AOTgetProperties
TreeNode .AOTname
|
PropertyInfo |
Dans X++, la AOTgetProperties méthode retourne une chaîne longue qui contient des paires nom-valeur pour toutes les propriétés de l’objet TreeNode. La AOTname méthode retourne une chaîne qui contient uniquement la valeur de la propriété name. |
TreeNode .AOTsave
TreeNode .AOTinsert
|
System .Reflection .Emit (espace de noms des classes) |
La AOTsave méthode applique les modifications d’un TreeNode objet dans votre code X++ à l’AOT, et les modifications sont conservées. Pour obtenir un exemple de code volumineux, consultez TreeNode.AOTsave, méthode. |
Comparaison : Classes sur les E/S de fichier
Il existe plusieurs classes qui effectuent des opérations d’entrée et de sortie de fichier (E/S). Dans le .NET Framework utilisé en C#, les équivalents de ces classes résident dans l’espace System.IO de noms.
Le tableau suivant répertorie plusieurs classes .NET Framework pour C# qui se trouvent dans l’espace System.IO de noms. Chaque ligne du tableau affiche la classe ou la méthode X++ qui correspond le mieux à la classe .NET Framework.
| X++ | C# | Commentaires |
|---|---|---|
BinaryIo |
FileStream
BinaryReader
BinaryWriter
|
Les classes X++ telles que BinaryIo celles qui s’étendent de la classe Io abstraite servent de flux, et elles servent également de lecteur et d’enregistreur pour ce flux. En C#, le flux est une classe distincte de la classe qui a des méthodes de lecture et d’écriture plus spécifiques. |
TextBuffer |
MemoryStream |
Ces classes contiennent une mémoire tampon en mémoire, et certaines des méthodes traitent la mémoire tampon comme s’il s’agissait d’un fichier sur le disque dur. |
| WINAPI ::createDirectory WINAPI ::folderExists WINAPI ::removeDirectory |
Directory
DirectoryInfo
Path
|
X++ peut utiliser des méthodes statiques dans la WINAPI classe pour de nombreuses fonctions de système d’exploitation de base qui impliquent des répertoires. |
| WINAPI ::getDriveType |
DriveInfo
DriveType
|
Ces classes et méthodes sont utilisées pour obtenir des informations relatives au lecteur. |
| WINAPI ::copyFile WINAPI ::createFile WINAPI ::d eleteFile WINAPI ::fileExists |
File
FileAttributes
FileInfo
|
X++ peut utiliser des méthodes statiques dans la WINAPI classe pour de nombreuses fonctions de système d’exploitation de base qui impliquent des fichiers. |
CommaIo
Comma7Io
|
(Aucune classe correspondante.) | Ces classes X++ peuvent générer des fichiers que Microsoft Excel peut importer. Dans X++ une référence de bibliothèque EPPlus est disponible pour une interaction supplémentaire avec Excel. |
AsciiIo
TextIo
|
FileStream
TextReader
TextWriter
|
Ces classes utilisent différentes pages de code. |
Io |
Stream
StreamReader
StreamWriter
FileStream
|
Elles sont souvent utilisées comme classes de base que d’autres classes étendent. |
CodeAccessPermission
FileIoPermission
|
System.Security
.CodeAccessPermission L’espace de noms System.Security.Permissions inclut les classes suivantes :
|
Concepts et méthodes de , assertet demand s’appliquent revertAssertaux deux langages. Toutefois, les deny méthodes et revertDeny les méthodes disponibles en C# ne sont pas disponibles dans X++. |
Comparaison X++, ANSI SQL : SQL Select
Dans X++, la syntaxe de l’instruction SQL select diffère de la spécification ANSI (American National Standards Institute).
Sélection d’une table unique
Le tableau suivant répertorie les différences entre les instructions select de X++ SQL et ANSI SQL.
| Caractéristique | X++ SQL | ANSI SQL | Commentaires |
|---|---|---|---|
| Nom de la table sur la clause from . | La clause from répertorie une instance de mémoire tampon d’enregistrement déclarée à partir d’une table, telle que celle de la CustTable table. |
La clause from répertorie un nom de table, et non le nom d’une mémoire tampon. | La mémoire tampon d’enregistrement a toutes les méthodes dont la xRecordclasse a dans X++. |
| Séquence de syntaxe de l’ordre par rapport aux clauses Where . | La clause order by doit apparaître avant la clause Where . La clause order by doit apparaître après la clause from ou join . La clause group by doit suivre les mêmes règles de positionnement de syntaxe que celles de l’ordre. | La clause order by doit apparaître après la clause Where . La clause Where doit apparaître après la clause from ou join . | Dans X++ et ANSI SQL, les clauses from et join doivent apparaître avant les clauses order by et where . |
| Négation de condition. | Le point d’exclamation (' !') est utilisé pour la négation. | Le mot clé non utilisé pour la négation. | X++ ne prend pas en charge la syntaxe !like. Au lieu de cela, vous devez appliquer le ! opérateur vers une clause. |
| Caractères génériques pour l’opérateur semblable . | 0 à plusieurs – Astérisque ('*') Exactement 1 – Point d’interrogation (' ?') |
0 à plusieurs – Signe de pourcentage ('%') Exactement 1 – Barre inférieure ('_') |
|
| Opérateurs logiques dans la clause Where . | Et - && Ou - || |
Et - et Ou - ou |
Exemple de code
L’exemple de code suivant illustre les fonctionnalités du tableau précédent.
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*') && 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
***/
Mots clés SQL X++
Les mots clés SQL X++ suivants sont parmi ceux qui ne font pas partie d’ANSI SQL :
- crosscompany
- firstonly100
- forceliterals
- forcenestedloop
- forceplaceholders
- forceselectorder
- validtimestate
Join, clause
Le tableau suivant répertorie les différences relatives au mot clé de jointure de X++ SQL et ANSI SQL.
| Caractéristique | X++ SQL | ANSI SQL | Commentaires |
|---|---|---|---|
| Liste des colonnes. | Les colonnes de la liste des colonnes doivent toutes provenir de la table répertoriée dans la clause from , et non d’une table dans une clause de jointure . Les colonnes de la liste ne peuvent pas être qualifiées par leur nom de table. | Les colonnes de la liste des colonnes peuvent provenir de n’importe quelle table dans les clauses from ou join . Il aide d’autres personnes à conserver votre code lorsque vous qualifiez les colonnes de la liste avec leur nom de table. | Pour plus d’informations, consultez Sélectionner des instructions sur les champs. |
| Syntaxe de clause Join. | La clause join suit la clause where . | La clause join suit une table dans la clause from . | Dans l’exemple de code X++, les critères de jointure sont une égalité de SalesPoolId valeurs. |
| Mot clé interne . | Le mode de jointure par défaut est la jointure interne. Il n’y a pas de mot clé interne . | Le mode de jointure par défaut est la jointure interne. Le mot clé interne est disponible pour rendre le code explicite. | Le mot clé externe existe dans SQL X++ et ANSI SQL. |
| Mots clés gauche et droit . | Les mots clés gauche et droit ne sont pas disponibles. Toutes les jointures sont laissées. | Les mots clés gauche et droit sont disponibles pour modifier le mot clé de jointure . | Aucun commentaire. |
| Opérateur d’égalité. | L’opérateur de signe égal double (''==) est utilisé pour tester l’égalité de deux valeurs. |
L’opérateur d’authentification unique (''=) est utilisé pour tester l’égalité de deux valeurs. |
Aucun commentaire. |
Exemple de code
L’exemple de code suivant illustre la syntaxe de jointure dans 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);
}
}
Champs d’agrégation
Le tableau suivant répertorie certaines différences dans la façon dont les champs d’agrégation de la liste de colonnes select sont référencés entre X++ SQL et ANSI SQL. Les champs d’agrégation sont ceux dérivés par des fonctions telles que somme ou moyenne.
| Caractéristique | X++ SQL | ANSI SQL | Commentaires |
|---|---|---|---|
| Alias de nom de champ d’agrégation. | La valeur d’agrégation se trouve dans le champ qui a été agrégé. | Vous pouvez utiliser le mot clé comme mot clé pour baliser un champ d’agrégation avec un alias de nom. L’alias peut être référencé dans le code suivant. | Pour plus d’informations, consultez Fonctions d’agrégation : différences entre X++ et SQL |
Exemple de code
Dans l’exemple de code suivant, l’appel à la méthode d’informations illustre la façon de référencer des champs d’agrégation (voir 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.
***/
Autres différences
Le tableau suivant répertorie d’autres différences de l’instruction select entre les sql X++ et ANSI SQL.
| Caractéristique | X++ SQL | ANSI SQL | Commentaires |
|---|---|---|---|
| Mot clé ayant . | Il n’y a pas de mot clé. | Le mot clé ayant le mot clé vous permet de spécifier des critères de filtre pour les lignes générées par la clause group by. | Aucun commentaire. |
| Résultats Null. | Dans une instruction while select, si la clause where filtre toutes les lignes, aucune ligne de nombre spécial n’est retournée pour signaler cela. | Dans une sélection, si la clause where filtre toutes les lignes, une ligne de nombre spécial est retournée. La valeur du nombre est 0. | Aucun commentaire. |
| Curseurs pour la navigation dans les lignes retournées. | L’instruction while select fournit des fonctionnalités de curseur. L’alternative consiste à utiliser le mot clé suivant . | Vous pouvez déclarer un curseur pour effectuer une boucle dans les lignes retournées à partir d’une instruction select . | |
| Clause From . | Le mot clé from est facultatif lorsqu’aucune colonne n’est répertoriée et qu’une seule table est référencée. Les deux options de syntaxe suivantes sont équivalentes : select \* from tCustTable; select tCustTable; |
Une instruction select ne peut pas lire à partir d’une table, sauf si la clause from est utilisée. | Dans X++ SQL, l’instruction select simple remplit la variable de mémoire tampon de table avec la première ligne retournée. Ceci est illustré par le fragment de code suivant : select \* from tCustTable; info(tCustTable.Name); |