Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Observação
Grupos de interesse da comunidade mudaram do Yammer para o Microsoft Viva Engage. Para ingressar em uma comunidade do Viva Engage e participar das discussões mais recentes, preencha o formulário Solicitar acesso às Finanças e Operações viva engage community e escolha a comunidade que você deseja ingressar.
Este artigo compara a sintaxe e a programação de X++ e C#.
Comparação X++, C#: Olá, Mundo
Esta seção compara o programa X++ mais simples com seu equivalente em C#.
Comparações de X++ a C#
As seções a seguir descrevem algumas semelhanças básicas e diferenças entre X++ e C#.
Semelhanças
Os seguintes recursos X++ são os mesmos para C#:
- Comentários de linha única (
//) e de várias linhas (/* */). -
==Operador (igual) para determinar se dois valores são iguais. -
!=Operador (não igual a) para determinar se dois valores não são equivalentes. -
+Operador (sinal de adição) para concatenação de cadeia de caracteres.
Diferenças
A tabela a seguir lista os recursos X++ que são diferentes em C#.
| Característica | X++ | C# | Comments |
|---|---|---|---|
if e else instruções condicionais |
A if instrução aceita qualquer tipo de expressão que possa ser convertida automaticamente em um booliano. Exemplos comuns incluem um int para o qual 0 significa falso ou um objeto para o qual nulo significa falso. |
A if instrução requer uma expressão booliana. |
A estrutura de sintaxe em relação a chaves e parênteses é exatamente a mesma entre X++ e C#. |
| Cadeia de caracteres literal | Uma cadeia de caracteres literal pode ser delimitada usando um dos seguintes métodos:
|
Uma cadeia de caracteres literal deve ser delimitada por um par de caracteres de aspas duplas ("). | Para X++, os caracteres de aspas duplas geralmente são usados para delimitar cadeias de caracteres. No entanto, é conveniente delimitar uma cadeia de caracteres com caracteres de aspas simples quando sua cadeia de caracteres deve conter um caractere de aspas duplas. |
queimar type |
Não há um char ou um tipo de caractere em X++. Você pode declarar um str de comprimento, mas ainda é uma cadeia de caracteres:str 1 myString = "a"; |
Há um char em C#. Você não pode passar um char parâmetro como para um método que insira um string parâmetro, embora você possa primeiro converter explicitamente em char um string. |
Para obter mais informações sobre tipos de dados X++, consulte Tipos de Dados Primitivos. |
| Saída de mensagens | O X++ entrega mensagens ao usuário na janela do Infolog. Os métodos comuns incluem:
|
Para um programa de linha de comando, as mensagens podem ser entregues ao console. Os métodos comuns incluem:
|
Exemplos de X++ e C#
Esta seção contém dois exemplos de código simples. Um exemplo é escrito em X++, e o outro está em C#. Ambos os exemplos alcançam o mesmo resultado. Os seguintes recursos X++ são demonstrados:
-
//comentário de linha única -
/\*\*/comentário de várias linhas - Instrução
if - Operador
== - Operador
!= -
+operador para concatenar cadeias de caracteres - Global::info para saída de mensagem, com e sem o prefixo Global::
- Global::error for message output
- O uso de caracteres de aspas simples e duplas (' e ") como delimitadores de cadeia de caracteres.
Observação
A melhor prática é usar aspas duplas para qualquer cadeia de caracteres que possa ser exibida ao usuário.
Exemplo de X++
Este exemplo de código X++ está na forma de um trabalho. Há um nó intitulado Trabalhos na Árvore de Objetos do Aplicativo (AOT). Este exemplo pode ser adicionado no nó Trabalhos e, em seguida, o trabalho pode ser executado.
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.");
}
}
Saída
Aqui está a saída da janela Infolog: Mensagem (09:49:48) Olá, Mundo, 1. Olá, Mundo, 2. Isso é como informações, mas é para avisos, 3. Isso é como informações, mas é para erros, 4.
Exemplo de C#
O programa C# a seguir é uma reescrita do programa X++ anterior.
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.");
}
}
}
Saída
Aqui está a saída real para o console do 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.
Comparação X++, C#: Loops
Esta seção compara os recursos de loop entre X++ e C#.
Semelhanças
Os seguintes recursos são os mesmos em X++ e C#:
- Declarações para variáveis do tipo de dados primitivo int. As declarações para outros tipos primitivos são quase as mesmas, mas os tipos podem ter nomes diferentes.
- instrução while para loops.
- instrução break para sair de um loop.
- instrução continue a saltar até a parte superior de um loop.
- <= (menor ou igual) operador de comparação.
Diferenças
A tabela a seguir lista os recursos X++ que são diferentes em C#.
| Features | X++ | C# | Comments |
|---|---|---|---|
A for instrução. |
A instrução for está disponível para loops. | A instrução C# for é ligeiramente diferente de for em X++. |
No C#, você pode declarar o inteiro do contador na for instrução. Mas no X++ o contador deve ser declarado fora da for instrução. |
| Operador de incremento ++. | Um operador de incremento ++ está disponível em X++. Mas uma variável int decorada com ++ só pode ser usada como uma instrução, não como uma expressão. Por exemplo, as seguintes linhas de código X++ não seriam compiladas:int age=42;print age++;No entanto, as seguintes linhas de código X++ seriam compiladas: int age=42;age++; print age; |
O operador C# ++ é mais flexível do que no X++. | As seguintes linhas de código são as mesmas em ambos os idiomas:
|
| operador modulo. | Em X++ o operador de modulo é mod. | Em C#, o operador de modulo é %. | Os símbolos do operador modulo são diferentes, mas seu comportamento é o mesmo em ambos os idiomas. |
| Suspenda temporariamente um programa de console que já foi iniciado. | A pause instrução. |
No C#, um programa de linha de comando pode ser pausado pela seguinte linha de código:Console.In.Read(); |
No X++, você continua clicando em um botão OK em uma caixa de diálogo modal. No C#, você continua pressionando qualquer teclado no teclado. |
| Exibir uma mensagem. | Em X++, a instrução print exibe uma mensagem na janela Imprimir. |
Em C#, uma mensagem pode ser exibida no console pela seguinte linha de código:Console.WriteLine(); |
A função X++ print é usada somente quando você testa. Um programa X++ que usa print quase sempre usa a pause instrução em algum lugar mais tarde no código. Para código X++ de produção, use o método Global::info em vez de print. A strfmt função geralmente é usada junto com info. Não há uma razão para usar pause depois info. |
| Faça um som. | A função de bipe faz um som que você pode ouvir. | Em C#, um som que você pode ouvir é emitido pela seguinte linha de código:Console.Beep(); |
Cada uma das instruções produz um tom curto. |
Imprimir e Global::info
Os exemplos de código X++ para loops usam a print função para exibir resultados. No X++, você pode usar a print instrução pode exibir qualquer tipo de dados primitivo sem precisar chamar funções que a convertem em uma cadeia de caracteres primeiro. Isso torna print útil em situações de teste rápidas. Geralmente, o método Global::info é usado com mais frequência do que print. O info método só pode exibir cadeias de caracteres. Portanto, a função strfmt é frequentemente usada junto com info. Uma limitação é print que você não pode copiar o conteúdo da janela Imprimir para a área de transferência (como com Ctrl+C). Gravações globais::info na janela do Infolog que dá suporte à cópia para a área de transferência.
Exemplo 1: o loop while
A palavra-chave while dá suporte a looping em X++ e C#.
Exemplo de 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.
}
Saída
A saída na janela Impressão X++ é a seguinte:
1
2
3
4
Exemplo de 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();
}
}
Saída
A saída do console do programa C# é a seguinte:
1
(Press any key to resume.)
2
(Press any key to resume.)
3
(Press any key to resume.)
4
(Press any key to resume.)
Exemplo 2: o loop for
A palavra-chave for dá suporte a looping em X++ e C#.
Exemplo de X++ para
Em X++, a variável de contador não pode ser declarada como parte da instrução 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;
}
Saída
A saída na janela Impressão X++ é a seguinte:
1
2
3
4
Exemplo de C# para
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();
}
}
Saída
A saída do console do programa C# é a seguinte:
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.)
Comparação X++, C#: Alternar
Em X++ e C#, a instrução switch envolve o caso, a quebra e o padrão das palavras-chave. A tabela a seguir lista as diferenças na instrução switch entre X++ e C#.
| Característica | X++ | C# | Comments |
|---|---|---|---|
break; no final de cada bloco de maiúsculas e minúsculas |
Em X++, quando qualquer bloco de caso corresponde ao valor da expressão na cláusula switch , todos os outros blocos demaiúsculas e minúsculas são executados até que uma break; instrução seja atingida. Nenhuma break; instrução é necessária em uma instrução de comutador X++, mas break; as instruções são importantes em quase todas as situações práticas. |
Em C#, uma break; instrução é sempre necessária após as instruções em um caso ou bloco padrão . Se uma cláusula case não tiver instruções entre si e a próxima cláusula case , uma break; instrução não será necessária entre as duas cláusulas case . |
É recomendável não omitir a break; instrução após qualquer bloco de caso, pois ela pode confundir o próximo programador que edita o código. |
break;no final do bloco padrão |
No X++ não há um efeito de adicionar uma break; instrução no final do bloco padrão . |
Em C#, o compilador requer uma break; instrução no final do bloco padrão . |
Para obter mais informações, consulte Switch Statements. |
| Somente valores constantes em um bloco de maiúsculas e minúsculas | No X++, você pode especificar um valor literal ou uma variável em um bloco de maiúsculas e minúsculas. Por exemplo, você pode escrever case myInteger:. | No C#, você deve especificar exatamente um valor literal em cada bloco de maiúsculas e minúsculas e nenhuma variável é permitida. | Sem comentários. |
| Vários valores em um bloco de maiúsculas e minúsculas | No X++, você pode especificar vários valores em cada bloco de maiúsculas e minúsculas. Os valores devem ser separados por uma vírgula. Por exemplo, você pode escrever case 4,5,myInteger:. |
No C#, você deve especificar exatamente um valor em cada bloco de maiúsculas e minúsculas. | No X++ é melhor gravar vários valores em um bloco de maiúsculas e minúsculas do que omitir a break; instrução no final de um ou mais blocos de maiúsculas e minúsculas. |
Exemplos de código para comutador
As seções a seguir mostram instruções de comutador comparáveis em X++ e C#.
Exemplo de comutador X++
O exemplo de comutador X++ mostra o seguinte:
-
case iTemp:ecase (93-90):para mostrar que as expressões maiúsculas e minúsculas não estão limitadas a constantes, como estão em C#. -
//break;para mostrar quebreak;as instruções não são necessárias no X++, embora sejam quase sempre desejáveis. -
case 2, (93-90), 5:para mostrar que várias expressões podem ser listadas em uma cláusula case em 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
***
Exemplo de comutador C#
O exemplo de comutador C# mostra o seguinte:
- caso 1: tem um comentário explicando que somente expressões constantes podem ser fornecidas em uma cláusula case .
-
break;as instruções ocorrem após a última instrução em cada bloco de maiúsculas e minúsculas que tem instruções, conforme exigido pelo 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
>>
***/
Comparação X++, C#: Caso de cadeia de caracteres e delimitadores
Esta seção compara o tratamento de cadeias de caracteres com maiúsculas e minúsculas misturadas em X++ e C#. Ele também explica os delimitadores de cadeia de caracteres que estão disponíveis no X++.
Semelhanças
Os seguintes recursos X++ são os mesmos do C#:
- A barra invertida (\) é o operador de escape para delimitadores de cadeia de caracteres.
- O sinal de at (@) anula o efeito de escape da barra invertida quando o sinal de at é gravado imediatamente antes da aspa aberta de uma cadeia de caracteres.
- O sinal de adição (+) é o operador de concatenação de cadeia de caracteres.
Diferenças
Os recursos X++ que são diferentes em C# são listados na tabela a seguir.
| Característica | X++ | C# | Comments |
|---|---|---|---|
== operador de comparação |
Não diferencia: o == operador não diferencia diferenças na caixa de caracteres. |
Em C#, o == operador é sensível às diferenças na caixa de caracteres. |
No X++, você pode usar a Função strCmp para comparações sensíveis a maiúsculas de minúsculas entre cadeias de caracteres. |
| Delimitadores de cadeia de caracteres | No X++, você pode usar a aspas única (') ou dupla (") como delimitador de cadeia de caracteres.Nota: Normalmente, a melhor prática é usar aspas duplas para cadeias de caracteres que podem ser exibidas para o usuário. No entanto, é conveniente delimitar uma cadeia de caracteres com aspas simples quando uma aspa dupla é um dos caracteres na cadeia de caracteres. |
No C#, você deve usar a aspa dupla como delimitador de cadeia de caracteres. Isso se refere ao tipo System.String. |
Em X++ e C#, você tem a opção de inserir um delimitador em uma cadeia de caracteres literal e escapá-lo com . No X++ você também tem a alternativa de inserir aspas simples em uma cadeia de caracteres delimitada por aspas duplas (ou o inverso), sem precisar usar a escape. |
| Delimitadores de caracteres | X++ tem um tipo de dados de cadeia de caracteres (str), mas nenhum tipo de caractere. |
No C#, você deve usar a única aspa como delimitador de caracteres. Isso se refere ao tipo System.Char. |
No .NET Framework, um System.String de comprimento é um tipo de dados diferente de um System.Char caractere. |
Exemplo 1: Diferenciação de maiúsculas e minúsculas do operador ==
Os == operadores != e != não diferenciam maiúsculas de minúsculas em X++, mas diferenciam maiúsculas de minúsculas em C#, conforme ilustrado pelo exemplo a seguir.
| X++ | C# | Comments |
|---|---|---|
"HELLO" == "hello" True em X++. |
"HELLO" == "hello" False em C#. |
Comparações de caso diferentes entre X++ e C#. |
Exemplo 2: o operador + concatenação de cadeia de caracteres
Os operadores + e += são usados para concatenar cadeias de caracteres em X++ e C#, conforme mostrado pelos exemplos na tabela a seguir.
| X++ | C# | Comments |
|---|---|---|
myString1 = "Hello" + " world"; O resultado é a igualdade: myString1 == "Hello world" |
(O mesmo que para X++.) | Em X++ e C#, o comportamento do operador + depende do tipo de dados de seus operandos. O operador concatena cadeias de caracteres ou adiciona números. |
mystring2 = "Hello"; myString2 += " world"; O resultado é a igualdade: myString2 == "Hello world" |
(O mesmo que para X++.) | Em X++ e C#, as seguintes instruções são equivalentes: a = a + b; a += b; |
Exemplo 3: Delimitadores de cadeia de caracteres de inserção e escape
Aspas simples ou duplas podem ser usadas para delimitar cadeias de caracteres em X++. O caractere de escape (\) pode ser usado para inserir delimitadores em uma cadeia de caracteres. Elas são ilustradas na tabela a seguir.
| X++ | C# | Comments |
|---|---|---|
myString1 = "They said \"yes\"."; Resultado: They said "yes". |
(O mesmo que para X++.) | O caractere de escape permite inserir delimitadores de cadeia de caracteres dentro de cadeias de caracteres. |
myString2 = 'They said "yes".'; Resultado: They said "yes". |
A sintaxe C# não permite que aspas simples delimitem cadeias de caracteres. | Para cadeias de caracteres que podem ser vistas pelo usuário, é considerada uma prática recomendada usar o caractere de escape em vez das aspas simples, conforme mostrado no exemplo. |
myString3 = "They said 'yes'."; Resultado: They said 'yes'. |
(O mesmo que para X++.) | No X++, as aspas simples não são tratadas como delimitadores, a menos que a cadeia de caracteres comece com um delimitador de aspas simples. Em C#, a aspa única não tem nenhum significado especial para cadeias de caracteres e não pode ser usada para delimitar cadeias de caracteres. Em C#, a aspa única é o delimitador necessário para literais do tipo System.Char. X++ não tem nenhum tipo de dados de caractere. |
str myString4 = 'C'; Aqui, a aspa única é um delimitador de cadeia de caracteres. |
char myChar4 = 'C'; Aqui, a única aspa é um System.Char delimitador, não um System.String delimitador. |
O X++ não tem nenhum tipo de dados que corresponda ao System.Char .NET Framework. Uma cadeia de caracteres X++ limitada a um comprimento de uma ainda é uma cadeia de caracteres, não um tipo de dados de caractere. |
Exemplo 4: caractere de escape único
Exemplos que ilustram o caractere de escape único na entrada ou na saída são mostrados na tabela a seguir.
| X++ | C# | Comments |
|---|---|---|
myString1 = "Red\ shoe"; Resultado: Red shoe |
Uma cadeia de caracteres literal em C# não pode conter a sequência de dois caracteres de escape seguida por um espaço, como "\ ". Ocorre um erro do compilador. | Quando o compilador X++ encontra a sequência de dois caracteres de "\ ", ele descarta o caractere de escape único. |
myString2 = "Red\\ shoe"; Resultado: Red\ shoe |
(O mesmo que para X++.) | Em um par de caracteres de escape, o primeiro nega o significado especial do segundo. |
Comparação: Sintaxe de matriz
Há semelhanças e diferenças nos recursos e sintaxe para matrizes em X++ versus C#.
Semelhanças
No geral, há muita semelhança na sintaxe e no tratamento de matrizes em X++ e C#. No entanto, há muitas diferenças.
Diferenças
A tabela a seguir lista áreas na sintaxe [] para matrizes diferentes para X++ e C#.
| Categoria | X++ | C# | Comments |
|---|---|---|---|
| Declaração | Uma matriz é declarada com colchetes acrescentados ao nome da variável. | Uma matriz é declarada com colchetes acrescentados ao tipo de dados. | int myInts[]; // X++ Nota: Uma matriz X++ não pode ser um parâmetro em um método.
|
| Declaração | A sintaxe da matriz dá suporte apenas a tipos de dados primitivos, como int e str. A sintaxe não dá suporte a classes ou tabelas. |
A sintaxe da matriz dá suporte a tipos de dados primitivos e classes. | No X++, você pode usar a Array Matriz para uma matriz de objetos. |
| Declaração | X++ é limitado a matrizes de dimensão única (myStrings[8]). | O C# adiciona suporte para matrizes multidimensionais (myStrings[8,3]) e para matrizes irregulares (myStrings[8][3]). | No X++ você não pode ter uma matriz de matrizes. No entanto, há uma sintaxe avançada para limitar a quantidade de memória ativa que uma grande matriz pode consumir, que se parece com a sintaxe multidimensional em C#: int int IntArray[1024,16];. Para obter mais informações, consulte Otimizações de desempenho de práticas recomendadas: trocando matrizes por disco. |
| Declaração | Em X++ uma matriz é uma construção especial, mas não é um objeto. | Em C#, todas as matrizes são objetos, independentemente das variações de sintaxe. | X++ tem uma classe Array, mas seu mecanismo subjacente difere das matrizes criadas usando a sintaxe []. Em C#, todas as matrizes usam o mesmo mecanismo subjacente, independentemente de [] a sintaxe da System.Array classe ser usada em seu código. |
| Length | Em X++, o comprimento de uma matriz de tamanho estático é determinado na sintaxe da declaração. | Em C#, o tamanho de uma matriz é determinado quando o objeto de matriz é construído. | Quando você usa a sintaxe da declaração [] em X++, não é necessário mais preparação antes de atribuir valores à matriz. No C#, você deve declarar e, em seguida, construir a matriz antes de atribuir a ela. |
| Length | Uma matriz X++ pode ter um comprimento dinâmico que pode ser aumentado mesmo após o início da população. Isso se aplica somente quando a matriz é declarada sem um número dentro do []. O desempenho poderá ser desacelerado se o comprimento da matriz dinâmica for aumentado muitas vezes. | Em C#, o comprimento de uma matriz não pode ser alterado depois que o comprimento é definido. | No fragmento a seguir do código X++, apenas a myInts matriz é dinâmica e pode aumentar de tamanho. int myInts[]; int myBools[5]; myInts[2] = 12; myInts[3] = 13; myBools[6] = 26; //Error |
| Length | Você pode obter o comprimento de algumas matrizes usando a dimOf função. |
Matrizes C# são objetos que têm uma Length propriedade. |
Sem comentários. |
| Indexação | A indexação de matriz é baseada em 1. | A indexação de matriz é baseada em 0. | mtIntArray[0] causaria um erro em X++. |
| Constante | Em X++, um valor constante é melhor obtido usando a diretiva de pré-preenchimento #define. | Em C#, você pode decorar sua declaração de variável com a palavra-chave const, para obter um valor constante. | X++ não tem palavra-chave const . O C# não pode atribuir valores a variáveis que são criadas por sua diretiva de pré-preenchimento #define. |
Exemplos de X++ e C#
Os exemplos de código a seguir mostram como matrizes de tipos de dados primitivos são tratadas. O primeiro exemplo está em X++, e o segundo exemplo está em C#. Ambos os exemplos obtêm os mesmos resultados.
Exemplo de 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]));
}
}
Saída
A saída para o Infolog é a seguinte:
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
Exemplo de 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
Saída
A saída do programa C# para o console de linha de comando é a seguinte:
-------- 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]
Recursos adicionais do X++ semelhantes à matriz
O contêiner é um tipo de dados especial que está disponível no X++. Ele pode ser considerado como semelhante a uma matriz ou semelhante a uma List coleção.
Comparação: coleções
Em um aplicativo de finanças e operações, você pode usar a classe de coleção X++ List . O .NET Framework usado em C# tem uma classe semelhante chamada System.Collections.Generic.List.
Comparando o uso das classes de lista
A tabela a seguir compara os métodos na classe X++ List com os métodos System.Collections.Generic.List do .NET Framework e do C#.
| Característica | X++ | C# | Comments |
|---|---|---|---|
| Declaração de coleção | List myList; |
List<string> myList; |
A declaração X++ não inclui o tipo de elementos a serem armazenados. |
| Declaração do iterador | ListIterator iterListEnumerator enumer; |
Iter de cadeia de caracteres< IEnumerator>; | No X++ o ListIterator objeto tem métodos que podem insert e delete itens do List. O X++ ListEnumerator não pode modificar o conteúdo do List. No X++ o ListEnumerator objeto é sempre criado na mesma camada que o List. Isso nem sempre é verdade para ListIterator. |
| Obtendo um iterador | new ListIterator (myList)myList.getEnumerator() |
myList.GetEnumerator() |
Em X++ e C#, o objeto List tem um método getter para um enumerador associado. |
| Construtor | new List(Types::String) |
new List<string>() |
Informações sobre o tipo de objetos a serem armazenados dentro das List classes são fornecidas ao construtor em X++ e C#. |
| Atualizar dados | Enumerador – o enumerador se torna inválido se quaisquer itens no List item forem adicionados ou removidos.Iterador – o iterador tem métodos que inserem e excluem itens do List. O iterador permanece válido. |
Enumerador – o enumerador se torna inválido se quaisquer itens no List item forem adicionados ou removidos. |
Os enumeradores tornam-se inválidos depois que os itens são adicionados ou excluídos do List. em X++ e C#. |
| Atualizar dados | Em X++, a List classe tem métodos para adicionar itens no início ou no final da lista. |
Em C#, a List classe tem métodos para adicionar membros em qualquer posição na lista. Ele também tem métodos para remover itens de qualquer posição. |
Em itens X++, pode ser removido do List único por um iterador. |
Exemplo 1: Declaração de uma lista
Os exemplos de código a seguir estão em X++ e C# que declaram List coleções.
// X++
List listStrings ,list2 ,listMerged;
ListIterator literator;
// C#
using System;
using System.Collections.Generic;
List<string> listStrings ,list2 ,listMerged; IEnumerator<string> literator;
Exemplo 2: Construção de uma lista
Em ambos os idiomas, o tipo de itens que a coleção armazena deve ser especificado no momento da construção. Para tipos de classe, X++ não pode obter mais específico do que se o tipo é uma classe (Types::Class). Os exemplos de código a seguir estão em X++ e C#.
// X++
listStrings = new List( Types::String );
// C#
listStrings = new List<string>;
Exemplo 3: Adicionar itens a uma lista
Em X++ e C#, a coleção fornece um método para acrescentar um item ao final da coleção e para inserir um item no início. Em C#, a coleção fornece um método para inserção em qualquer ponto da coleção com base em um valor de índice. Em X++ um iterador de coleção pode inserir um item em sua posição atual. Os exemplos de código a seguir estão em X++ e 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");
Exemplo 4: iterar por meio de uma lista
X++ e C# têm classes de iterador que você pode usar para percorrer os itens em uma coleção, conforme mostrado nos exemplos a seguir.
// 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);
}
Exemplo 4b: foreach em C#
Em C#, a palavra-chave foreach geralmente é usada para simplificar a tarefa de iterar por meio de uma lista. O exemplo de código a seguir se comporta da mesma forma que o exemplo de C# anterior.
foreach (string currentString in listStrings)
{
Console.WriteLine(currentString);
}
Exemplo 5: excluir o segundo item
Os exemplos de código a seguir excluem o segundo item da coleção. No X++ isso requer um iterador. Em C#, a coleção em si fornece o método para remover um item.
// X++
literator.begin();
literator.next();
literator.delete();
// C#
listStrings.RemoveAt(1);
Exemplo 6: Combinar duas coleções
Os exemplos de código a seguir combinam o conteúdo de duas coleções em uma.
// X++
listStrings = List::merge(listStrings ,listStr3);
// Or use the .appendList method:
listStrings.appendList (listStr3);
// C#
listStrings.InsertRange(listStrings.Count ,listStr3);
Comparação: coleções de chaves com valores
Em um aplicativo de finanças e operações, você pode usar a classe de Map coleção. A Map coleção contém pares de valores, o valor da chave mais um valor de dados. Isso se assemelha à classe .NET Framework chamada System.Collections.Generic.Dictionary.
Semelhanças
A lista a seguir descreve as semelhanças entre X++ e C# em relação às suas coleções que armazenam pares chave-valor:
- Ambos impedem chaves duplicadas.
- Ambos usam um enumerador (ou iterador) para fazer loop pelos itens.
- Ambos os objetos de coleção chave-valor são construídos com designações dos tipos armazenados como chave e valor.
- Ambos podem armazenar objetos de classe e não estão limitados a armazenar primitivos como int.
Diferenças
A tabela a seguir descreve as diferenças entre X++ e C# em relação às classes de coleções que armazenam pares chave-valor:
| Característica | X++ | C# | Comments |
|---|---|---|---|
| Chaves duplicadas | Em X++, a Map classe impede chaves duplicadas tratando implicitamente sua chamada para seu insert método como uma operação para atualizar apenas o valor associado à chave. |
Em C#, a Dictionary classe gera uma exceção quando você tenta adicionar uma chave duplicada. |
Chaves duplicadas são impedidas em ambos os idiomas, embora por técnicas diferentes. |
| Excluir itens | Em X++, o delete método em um objeto iterador é usado para remover um par de chave-valor indesejado de um Map. |
Em C#, a Dictionary classe tem um remove método. |
Em ambos os idiomas, um enumerador será inválido se a contagem de itens de coleção for modificada durante a vida útil do enumerador. |
Exemplo 1: Declaração de uma coleção Key-Value
Em ambos os idiomas, o tipo de itens que a coleção chave-valor armazena deve ser especificado. Em X++ o tipo é especificado no momento da construção. Em C#, o tipo é especificado no momento da declaração e no momento da construção. Os exemplos de código a seguir estão em X++ e C#.
// X++
Map mapKeyValue;
MapEnumerator enumer;
MapIterator mapIter;
// C#
Dictionary<int,string> dictKeyValue;
IEnumerator<SysCollGen.KeyValuePair<int,string>> enumer;
KeyValuePair<int,string> kvpCurrentKeyValuePair;
Exemplo 2: Construção da coleção
Em ambos os idiomas, o tipo de itens que a coleção chave-valor armazena especificado durante a construção. Para tipos de classe, X++ não pode obter mais específico do que se o tipo é uma classe (Types::Class). Os exemplos de código a seguir estão em X++ e C#.
// X++
mapKeyValue = new Map(Types::Integer, Types::String);
// C#
dictKeyValue = new Dictionary<int,string>();
Exemplo 3: Adicionar um item à coleção
Não há quase nenhuma diferença em como um item é adicionado a uma coleção chave-valor em X++ e C#, conforme mostrado nos exemplos de código a seguir.
// X++
mapKeyValue.insert(xx ,int2str(xx) + “_Value”);
// C#
dictKeyValue.Add(xx ,xx.ToString() + “_Value”);
Exemplo 4: iterar por meio de uma coleção de Key-Value
Os enumeradores são usados para fazer loop por meio das coleções chave-valor em X++ e C#, conforme mostrado nos exemplos de código a seguir.
// 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.
}
Exemplo 5: atualizar o valor associado a uma chave
A sintaxe é muito diferente entre os dois idiomas para uma atualização do valor associado a uma determinada chave. Os exemplos de código de ollowing são para a chave 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.”;
Exemplo 6: Excluir um item
A sintaxe é muito diferente entre os dois idiomas para excluir um par chave-valor de uma coleção, enquanto itera por meio dos membros da coleção. Exemplos de código para a chave 102 são mostrados abaixo.
// 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);
Comparação: exceções
Há algumas semelhanças, mas muitas diferenças quando comparamos o comportamento relacionado à exceção entre X++ e C#. As palavras-chave try, catch e throw se comportam da mesma forma em X++ e C#. Mas os tipos de exceções geradas e capturadas são diferentes para os dois idiomas.
Semelhanças
As semelhanças entre X++ e C# em relação aos recursos de exceção incluem os seguintes exemplos:
- Ambos os idiomas têm a mesma palavra-chave try .
- Ambos têm a mesma palavra-chave catch .
- Ambos habilitam para uma instrução catch que não especifica nenhuma exceção específica. Tal instrução catch captura todas as exceções que a alcançam.
- Ambos têm a mesma palavra-chave de lançamento .
Diferenças
As diferenças relacionadas à exceção entre X++ e C# são descritas na tabela a seguir.
| Característica | X++ | C# | Comments |
|---|---|---|---|
| Repetir | Salta para a primeira instrução no bloco try associado. Para obter mais informações, consulte Tratamento de Exceções com palavras-chave try e catch. | A funcionalidade da palavra-chave de repetição pode ser imitada no código C#, mas não há uma palavra-chave correspondente. | Somente X++ tem uma palavra-chave de repetição . O C# não tem nenhum equivalente. Para obter mais informações, consulte X++, Comparação de C#: Repetição automatizada após uma exceção. |
| finalmente | A finally palavra-chave tem suporte para seguir as palavras-chave e try as catch palavras-chave. |
A palavra-chave por fim marca um bloco de código que segue os blocos try e catch . O final será executado independentemente de qualquer exceção ser lançada ou capturada. | A semântica é idêntica à semântica em C#. |
| Exceções específicas | No X++, uma exceção é um elemento da Exception enumeração, como Error, Deadlock ou CodeAccessSecurity. Nenhuma exceção pode conter outra. |
Em C#, uma exceção é uma instância da System.Exception classe base ou qualquer classe que herda dela. Uma exceção pode ser contida na InnerException propriedade da exceção gerada. |
Em X++ cada exceção gerada é um valor da enumeração Exceção. Para obter mais informações, consulte Enumeração de Exceção. |
| Mensagem de exceção | No X++, a mensagem criada quando uma exceção é gerada está disponível apenas no Infolog e a mensagem não está diretamente vinculada à exceção. | Em C#, a mensagem é o Message membro do System.Exception objeto. |
Em X++ o método Global::error é o mecanismo que exibe mensagens de exceção no Infolog. Para obter mais informações, consulte Tratamento de Exceções com palavras-chave try e catch. |
| Condições de exceção | Em X++ ocorre um erro quando você chama um método de instância em uma variável de objeto que ainda não teve nada atribuído a ele. No entanto, nenhuma exceção é gerada junto com esse erro. Portanto, nenhum catch bloco pode obter controle mesmo se a variável não atribuída for mal atribuída em um try bloco. No exemplo de código a seguir, o erro causado pelo código box4.toString(); não faz com que o controle seja transferido para nenhum catch bloco: DialogBox box4;try { box4.toString(); info("toString did not error, but expected an error."); } catch (Exception::Error) // Nenhum valor de exceção captura isso. { info("Invalid use of box4 gave control to catch, unexpected."); } |
Em C# é System.NullReferenceException gerado quando uma variável não inicializada é tratada como uma referência de objeto. |
Pode haver várias outras diferenças nas condições que geram exceções. |
| Transações SQL | Em X++ quando uma exceção SQL ocorre em uma transação ttsBegin - ttsCommit , nenhuma instrução catch dentro do bloco de transação pode processar a exceção. | Em C#, um bloco catch dentro de uma transação SQL pode capturar a exceção. |
Exemplos
Os seguintes recursos X++ são demonstrados:
- palavra-chave try .
- palavra-chave catch .
- O comportamento após uma exceção de Exceção::Erro ocorre.
Exemplo de 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.");
}
Saída
Aqui está a saída da janela do 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.
Exemplo de C#
O programa C# a seguir é uma reescrita do programa X++ anterior.
// 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
Saída
Aqui está a saída para o console do C#:
(e2) In catch block for -- System.IndexOutOfRangeException
'finally' is not an X++ keyword, although it's in C#.
End of program.
Comparação: Repetição automatizada após uma exceção
Às vezes, você pode escrever código em um bloco catch que corrige a causa de uma exceção que ocorre durante o tempo de execução. O X++ fornece uma palavra-chave de repetição que só pode ser usada dentro de um bloco catch . A palavra-chave de repetição permite que um programa volte para o início do bloco try depois que o problema tiver sido corrigido pelo código no bloco catch . C# não tem uma palavra-chave de repetição . No entanto, o código C# pode ser gravado para fornecer um comportamento equivalente.
Exemplos de código para repetição
O programa de exemplo X++ a seguir faz com que uma Exceção::Erro seja gerada. Isso ocorre quando ele tenta ler pela primeira vez um elemento da sStrings matriz usando um valor de índice inválido. Quando a exceção é capturada, a ação corretiva é executada durante o tempo de execução dentro do bloco catch . A instrução de repetição, em seguida, salta de volta para a primeira instrução no bloco try . Esta segunda iteração funciona sem encontrar nenhuma exceção.
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;
}
Saída
Aqui está a saída para a janela Imprimir:
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.
Exemplo de C#
O exemplo de C# a seguir não é uma tradução linha a linha do exemplo X++ anterior. Em vez disso, o programa C# tem uma estrutura diferente para que ele imite o comportamento da palavra-chave de repetição na qual o programa X++ depende. Os blocos try e catch estão em um método chamado. As variáveis usadas no bloco try são armazenadas no método de chamador. O método de chamador passa as variáveis como parâmetros decorados com a palavra-chave ref , para que seus valores possam ser corrigidos dentro do bloco catch do método chamado. O método chamado captura todas as exceções e retorna um booliano para se comunicar com o chamador se uma segunda chamada é necessária.
// 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;
}
}
Saída
Aqui está a saída para o 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.
Comparação: operadores
Esta seção compara os operadores entre X++ e C#.
Operadores de atribuição
A tabela a seguir exibe as diferenças entre os operadores de atribuição em X++ e C#.
| X++ e C# | Diferenças |
|---|---|
= |
Em X++ esse operador causa uma conversão implícita sempre que uma perda de precisão pode ocorrer, como para uma atribuição de um int64 para um int. Mas em C# a atribuição causa um erro de compilação. |
+= e -= |
A única diferença é que, em C#, esses operadores também são usados na manipulação de delegados. |
| ++ e -- | Esses são os operadores de incremento e decremento em ambos os idiomas. A seguinte linha é idêntica em ambos os idiomas:++myInteger;Mas em X++ esses dois operadores são para instruções, não para expressões. Portanto, as seguintes linhas geram erros de compilação em X++: myStr = int2str(++myInteger);myIntA = myIntBB++; |
Operadores aritméticos
A tabela a seguir lista os operadores aritméticos.
| X++ e C# | Diferenças |
|---|---|
| * | Como operador de multiplicação, não há diferenças. Nota: O asterisco também é usado nas instruções SQL que fazem parte da linguagem X++. Nessas instruções SQL, o asterisco também pode ser um dos seguintes:
|
/ |
O operador de divisão é o mesmo em X++ e C#. |
MOD |
Para operações de modulo, a única diferença é que o símbolo % é usado em C#. |
| + | O operador de adição é o mesmo em X++ e C#. O sinal de adição também é usado para concatenação de cadeia de caracteres. Esse operador adiciona números e concatena cadeias de caracteres em ambos os idiomas. |
| - | O operador de subtração é o mesmo em X++ e C#. |
Operadores bit a bit
A tabela a seguir compara os operadores bit a bit entre X++ e C#.
| X++ e C# | Diferenças |
|---|---|
| << | O operador de turno esquerdo é o mesmo em X++ e C#. |
| >> | O operador de deslocamento para a direita é o mesmo em X++ e C#. |
| ~ | O operador NOT bit a bit é o mesmo em X++ e C#. |
| & | O operador AND binário é o mesmo em X++ e C#. |
| ^ | O operador XOR binário é o mesmo em X++ e C#. |
Operadores relacionais
Os seguintes operadores relacionais são os mesmos em X++ e C#:
==<=<=><!=&&||!? :
Comparação: eventos
Há algumas diferenças na forma como X++ e C# implementam o padrão de design de evento. Para obter mais informações, consulte Terminologia de eventos e palavras-chave.
Comparação de eventos entre X++ e C#
Há diferenças na maneira como os delegados são usados para eventos em X++ versus C#.
| Conceito | X++ | C# | Comments |
|---|---|---|---|
| delegate | Em X++, um delegado pode ser declarado apenas como um membro em uma classe. Um delegado não pode ser um membro em uma tabela. Todos os delegados são membros de instância de sua classe, não membros estáticos . Nenhum modificador de acesso pode ser usado em uma declaração de delegado, pois todos os delegados são membros protegidos . Portanto, o evento só pode ser gerado por código dentro da mesma classe em que o delegado é membro. No entanto, a única exceção à natureza privada de um delegado é que o código fora de sua classe pode operar nos delegados usando os operadores += e -= . | Em C#, cada delegado é um tipo, assim como cada classe é um tipo. Um delegado é declarado independentemente de qualquer classe. Sem a palavra-chave do evento , você pode ter um delegado como um tipo de parâmetro em um método, assim como você pode ter uma classe como um tipo de parâmetro. Você pode construir uma instância de um delegado para passar para o valor do parâmetro. | Em X++, cada classe é um tipo, mas nenhum delegado é um tipo. Você não pode construir uma instância de um delegado. Nenhum delegado pode ser um parâmetro para um método. Mas você pode criar uma classe que tem um membro delegado e pode passar instâncias da classe como valores de parâmetro. Para obter mais informações, consulte palavras-chave X++. |
| acontecimento | No código X++, um evento é um dos seguintes:
|
Em C#, a palavra-chave do evento é usada para declarar um tipo delegado como membro de uma classe. O efeito da palavra-chave do evento é tornar o delegado protegido, mas ainda acessível para os operadores += e -= . Você pode assinar métodos de manipulador de eventos em um evento usando o operador +=. Um delegado pode ser útil sem a palavra-chave do evento , como uma técnica para passar um ponteiro de função como um parâmetro para um método. | Os eventos automáticos que ocorrem antes do início de um método e após o final de um método podem ser assinados apenas usando o AOT. |
| Operadores += e -= | No X++, você usa o operador += para assinar métodos a um delegado. O operador -= cancela a assinatura de um método de um delegado. | Em C#, você usa o operador += para assinar métodos em um evento ou para um delegado que não é usado com a palavra-chave do evento . | O delegado contém uma referência a todos os objetos que têm métodos inscritos no delegado. Esses objetos não são qualificados para coleta de lixo enquanto o delegado mantém essas referências. |
eventHandler |
No X++, a palavra-chave eventHandler é necessária quando você usa o operador += ou -= para assinar ou cancelar a assinatura de um método de um delegado. |
System.EventHandler é um tipo delegado no .NET Framework. |
Esse termo é usado de forma diferente em X++ do que em C# ou no .NET Framework. Para obter mais informações, consulte palavras-chave X++. |
Exemplo de X++
Os itens importantes a serem notados são os seguintes no exemplo X++:
O
XppClasstem um membro delegado chamadomyDelegate.Observação
O AOT contém um nó para o delegado. O nó está localizado nas classes > AOT > XppClass > myDelegate. Vários nós do manipulador de eventos podem ser localizados no nó myDelegate. Os manipuladores de eventos representados por nós no AOT não podem ser removidos pelo operador -= durante o tempo de execução.
As {} chaves no final da declaração delegada são necessárias, mas não podem ter nenhum código nelas.
O
XppClasstem dois métodos cujas assinaturas de parâmetro são compatíveis com o delegado. Um método é estático.Os dois métodos compatíveis são adicionados ao delegado com o operador += e a palavra-chave eventHandler . Essas instruções não chamam os métodos do manipulador de eventos, as instruções só adicionam os métodos ao delegado.
O evento é gerado por uma chamada para o delegado.
O valor do parâmetro passado para o delegado é recebido por cada método de manipulador de eventos.
O trabalho X++ curto na parte superior do exemplo inicia o teste.
// 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);
}
}
A saída do trabalho X++ anterior é a seguinte:
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.
Exemplo de C#
Esta seção contém um exemplo de código C# para o padrão de design de evento da amostra X++ anterior.
// 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);
}
}
A saída da amostra anterior do C# é a seguinte:
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.
Eventos e a AOT
Há outros sistemas de eventos que se aplicam somente a itens no AOT. Para obter mais informações, consulte Nós do Manipulador de Eventos no AOT.
Comparação: Diretivas de pré-preenchimento
X++ e C# compartilham algumas palavras-chave para sua sintaxe de diretiva de pré-preenchimento, mas os significados nem sempre são os mesmos.
Semelhanças
Os compiladores X++ e C# reconhecem muitas das mesmas palavras-chave. Na maioria dos casos, as palavras-chave significam o mesmo para ambos os compiladores de linguagem.
Diferenças
Uma diferença fundamental entre as diretivas de pré-preenchimento em X++ versus C# é a palavra-chave #define que ambos os pré-compiladores de idioma reconhecem. Ao contrário de C#, em X++ a diretiva #define requer um ponto em sua sintaxe. Em X++, parênteses podem ser usados para dar um valor ao símbolo definido. Essas diferenças são mostradas nos seguintes exemplos:
- Em X++: #define. InitialYear(2003)
- Em C#: #define InitialYear
Uma pequena diferença é que em C# pode haver espaços e caracteres de guia entre o caractere # e a palavra-chave de diretiva, como # definir Teste.
Palavras-chave idênticas
A tabela a seguir lista as diretivas de pré-preenchimento semelhantes em X++ e C#.
| Keyword | X++ | C# | Comments |
|---|---|---|---|
#define |
Em X++, um nome de variável de pré-preenchimento pode ser definido e um valor pode ser dado a essa variável. | Em C#, um nome de variável de pré-preenchimento pode ser definido, mas nenhum valor pode ser dado a essa variável. Além disso, qualquer #define em C# deve ocorrer na parte superior do arquivo e não pode ocorrer após qualquer código, como uma instrução using ou uma declaração de classe. | O compilador C# pode inserir um parâmetro de linha de /define comando para definir um nome de variável de pré-compilador sem definir a variável em qualquer arquivo de código C#. O compilador X++ não tem equivalente a /define. |
#if |
Em X++, #if pode determinar se existe uma variável de pré-compilador e se a variável tem um determinado valor. | Em C#, #if só pode determinar se existe uma variável de pré-preenchimento. Ele não pode testar nenhum valor porque nenhum valor pode ser atribuído. | |
#endif |
Em X++, #endif marca o fim de um bloco de #if. Ele também termina um bloco #ifnot. | Em C#, #endif marca o fim de um bloco de #if, independentemente de o bloco incluir um #else. |
Palavras-chave diferentes com o mesmo resultado de processamento
A tabela a seguir lista as diretivas de pré-preenchimento que são nomeadas de forma diferente em X++ e C#, mas que fornecem os mesmos resultados quando processadas.
| X++ | C# | Comments |
|---|---|---|
| #ifnot | #if #else | Não há uma diretiva #else no X++, mas o #ifnot fornece funcionalidade semelhante. No X++, #ifnot pode determinar se existe uma variável de pré-compilador e se a variável não tem um valor específico. Em C#, #if pode determinar se existe uma variável de pré-preenchimento quando o '!' o símbolo é prefixado no nome da variável. |
//BP Deviation documented |
aviso #pragma | Essas entradas X++ e C# não são equivalentes, mas há uma semelhança parcial. Ambos suprimem mensagens de aviso do compilador. |
| #macrolib | . Arquivo HPP no C++ | Há uma semelhança parcial entre a diretiva X++ #macrolib versus um . Arquivo HPP no C++. Ambos podem conter várias instruções #define. |
Diretivas de pré-preenchimento exclusivas para X++
A tabela a seguir lista as diretivas de pré-preenchimento X++ que não têm nenhum equivalente direto em C#.
| X++ | Comments |
|---|---|
| #linenumber | A diretiva #linenumber é para obter o número de linha, para que ele possa ser enviado para o Infolog. A diretiva C# #line é diferente porque sua finalidade é definir o número de linha. |
| #defdec #definc | |
| #globaldefine | No X++, há uma pequena diferença entre #globaldefine versus #define. A diferença é que #globaldefine nunca substitui um valor não nulo atual atribuído a uma variável de pré-compilador por #define. C# não tem nada semelhante a essa diferença, porque em C#, um nome de variável de pré-preenchimento não pode receber um valor. |
| #localmacro #macro | No X++, #localmacro permite atribuir um valor multilinha a uma variável de pré-preenchimento. #macro é um sinônimo, mas é recomendável #localmacro. Em C#, a diretiva #define tem parte dessa funcionalidade, mas não pode atribuir um valor a uma variável de pré-preenchimento. |
| #globalmacro | No X++, #globalmacro é quase o mesmo que o #localmacro preferencial. |
Comparação: Programação orientada a objetos
Os princípios de OOP (programação orientada a objeto) do X++ diferem de C#.
Comparações conceituais
A tabela a seguir compara a implementação de princípios OOP entre X++ e C#.
| Característica | X++ | C# | Comments |
|---|---|---|---|
| Elenco | A linguagem X++ tem as palavras-chave é e como, que são usadas para tornar os downcasts seguros e explícitos. Dica: X++ não requer o uso da palavra-chave como quando você reduziu uma variável de classe base para uma variável de classe derivada. No entanto, recomendamos que todas as instruções downcast usem a palavra-chave como palavra-chave. | Um objeto pode ser convertido para cima ou para baixo no caminho da herança. Os downcasts exigem a palavra-chave como . | Para obter mais informações sobre as palavras-chave X++ é e como, consulte Operadores de Expressão: Is e As for Inheritance. |
| Funções locais | Um método pode conter uma declaração e um corpo de código para zero ou mais funções locais. Somente esse método pode ter chamadas para a função local. | O C# 3.0 dá suporte a expressões lambda, que têm alguma semelhança com funções anônimas e funções locais. Expressões lambda são frequentemente usadas com delegados. | |
| Sobrecarga de método | Não há suporte para sobrecarga de método. Um nome de método pode ocorrer apenas uma vez por classe. | Há suporte para sobrecarga de método. Um nome de método pode ocorrer várias vezes em uma classe, com assinaturas de parâmetro diferentes em cada caso. | O X++ dá suporte a parâmetros opcionais em métodos. Parâmetros opcionais podem imitar parcialmente a sobrecarga de método. Para obter mais informações, consulte a linha para parâmetros opcionais nesta tabela. |
| Substituição de método | Há suporte para substituição de método. Uma classe derivada pode ter um método pelo mesmo nome que na classe base, desde que a assinatura do parâmetro seja a mesma em ambos os casos. A única exceção é que o método de substituição pode adicionar um valor padrão a um parâmetro. | Há suporte para substituição de método. A palavra-chave virtual deve ser aplicada a um método antes que o método possa ser substituído em uma classe derivada. | O conceito de substituir um método inclui o nome do método, sua assinatura de parâmetro e seu tipo de retorno. O conceito de substituição de método não se aplica se o método base e o método de substituição forem diferentes em qualquer um desses aspectos. |
| Parâmetros opcionais | Uma declaração de parâmetro pode ser seguida por uma atribuição de valor padrão. O chamador de método tem a opção de passar um valor para esse parâmetro ou ignorar o parâmetro para aceitar o valor padrão. Esse recurso imita a sobrecarga de método porque duas chamadas para o mesmo nome de método podem passar números diferentes de parâmetros. Cada parâmetro que tem um valor padrão deve seguir o último parâmetro que não tem um valor padrão. | Parâmetros opcionais são compatíveis com a palavra-chave params . Mesmo sem a palavra-chave params , do ponto de vista do chamador, a sobrecarga de método pode fornecer funcionalidade parcialmente semelhante. | Para obter mais informações, consulte Parâmetros e escopo e uso de parâmetros opcionais. |
| Herança única | Você pode derivar sua classe X++ de outra classe X++ usando a palavra-chave extends no nó classDeclaration de sua classe, no AOT. Nenhuma classe deriva implicitamente de outra classe. Se quiser que sua classe derive diretamente da Object classe, use a palavra-chave extends . Você pode especificar apenas uma classe na palavra-chave extends .Cuidado: ao modificar uma classe base X++ da qual outras classes derivam, você deve recompilar essa classe base usando o Compile forward. Essa opção garante que as classes derivadas também sejam recompiladas. Para garantir que as classes derivadas também sejam recompiladas, clique com o botão direito do mouse no nó de classe base e clique em Add-Ins > Compilar para frente. A alternativa de clicar em Compilar > Compilar (ou pressionar a tecla F7) às vezes é insuficiente para uma alteração de classe base. Uma classe pode implementar zero a muitas interfaces. Uma tabela X++ herda implicitamente da Common tabela e da xRecord classe. |
O C# usa a palavra-chave extends para derivar de outra classe. Todas as classes do .NET Framework derivam implicitamente da System.Object classe, a menos que elas derivam explicitamente de outra classe. |
Comparações de palavra-chave
A tabela a seguir lista as palavras-chave relacionadas ao OOP em X++ e C#.
| Keyword | X++ | C# | Comments |
|---|---|---|---|
| abstract | Não há diferença. | ||
| classe | Os modificadores públicos e privados são ignorados nas declarações de classe. Não há um conceito de um agrupamento de namespace de classes. Não há nenhum ponto (.) em nenhum nome de classe. | Os modificadores públicos e privados podem ser usados para modificar declarações de classe. O C# também tem a palavra-chave interna, que se relaciona com a forma como as classes são agrupadas em arquivos de assembly. | Não há conceito de uma classe protegida , apenas membros protegidos de uma classe. |
| Estende | Uma declaração de classe pode herdar de outra classe usando a palavra-chave extends . | Dois-pontos (:) é usado em que as palavras-chave se estendem e implementam são usadas em X++. | |
| final | Um método final não pode ser substituído em uma classe derivada. Uma classe final não pode ser estendida. | A palavra-chave selada em uma classe significa a mesma coisa que o final significa em uma classe X++. | |
| Implementa | Uma declaração de classe pode implementar uma interface usando a palavra-chave implements . | ||
| interface | Uma interface pode especificar métodos que a classe deve implementar. | Uma interface pode especificar métodos que a classe deve implementar. | |
| novo | A nova palavra-chave é usada para alocar uma nova instância de uma classe. Em seguida, o construtor é chamado automaticamente. Cada classe tem exatamente um construtor e o construtor é nomeado new. Você pode decidir quais parâmetros o construtor deve inserir. |
A nova palavra-chave é usada para criar uma nova instância de uma classe. Em seguida, o construtor é chamado automaticamente. Os próprios métodos de construtor não são nomeados new, eles têm o mesmo nome da classe.Nota: A nova palavra-chave também pode ser usada em um método, para modificar a maneira como o método substitui o mesmo método na classe base. |
X++ e C# pressupõem um construtor padrão para classes que não têm nenhum construtor explicitamente escrito em seu código. |
| zero | Não há diferença. | ||
| privado e protegido | As palavras-chave privadas e protegidas podem ser usadas para modificar a declaração de um membro de classe. | As palavras-chave privadas e protegidas podem ser usadas para modificar a declaração de um membro de classe. | |
| público | Um método que não é modificado com público, protegido ou privado tem o nível de acesso padrão de público. | Um método que não é modificado com público, protegido ou privado tem o nível de acesso padrão de privado. | |
| estático | Um método pode ser estático, mas um campo não pode. | Os métodos e os campos podem ser estáticos. | |
| súper | A super palavra-chave é usada em uma classe derivada para acessar o mesmo método em sua classe base. void method2(){ // Call method2 method // on the base class. super(); } |
A palavra-chave base é usada em uma classe derivada para acessar vários métodos em sua classe base. void method2() { // Call methods on // the base class. base.method2(); base.method3(); } |
Em C#, há uma sintaxe especial para usar a base para chamar o construtor base. |
| este | Para uma chamada de um método de instância para outro no mesmo objeto, um qualificador para o método chamado é necessário. A palavra-chave que está disponível como um qualificador para o objeto atual. | Para uma chamada de um método de instância para outro no mesmo objeto, um qualificador para o método chamado não é necessário. No entanto, essa palavra-chave está disponível como um qualificador para o objeto atual. Na prática, a palavra-chave pode ser útil exibindo informações do IntelliSense. | |
finalize |
A Object classe contém o finalize método. O finalize método não é final e pode ser substituído. O finalize método parece ser semelhante ao System.Object.Finalize método em C#, mas em X++ o finalize método não tem nenhum significado especial de qualquer tipo. Um objeto é removido automaticamente da memória quando a última referência ao objeto para de referenciar o objeto. Por exemplo, isso pode acontecer quando a última referência sai do escopo ou recebe outro objeto para referência. |
Os métodos Finalize e Dispose são comuns em alguns tipos de classes. O coletor de lixo chama o e Finalize os Dispose métodos quando ele destrói e objeto. |
Em C#, o System.GC.Collect método no .NET Framework pode ser chamado para iniciar o coletor de lixo. Não há uma função semelhante no X++ porque o X++ usa um coletor de lixo determinístico. |
main |
As classes invocadas de um menu têm seu main método chamado pelo sistema. |
Classes invocadas de um console de linha de comando têm seu Main método chamado pelo sistema. |
Comparação: classes
Quando você usa C# no .NET Framework, as classes são agrupadas em namespaces. Cada namespace se concentra em uma área funcional, como operações de arquivo ou reflexão. No entanto, quando você usa as classes em X++, não há agrupamentos visíveis como um namespace.
Comparação: classes sobre reflexão
No X++, a TreeNode classe fornece acesso à Árvore de Objetos do Aplicativo (AOT). A TreeNode classe é o centro da funcionalidade de reflexão em X++. A TreeNode classe e seus métodos podem ser comparados ao System.Reflection namespace no .NET Framework que o C# usa.
A tabela a seguir lista várias classes que estão disponíveis para você ao escrever código C#. Estas são classes do .NET Framework. Para esta tabela, todas as classes C# estão no System.Reflection namespace, a menos que sejam especificadas de outra forma. Cada linha mostra a classe correspondente, ou membro da classe, que está disponível para você quando o código de gravação X++.
| X++ | C# | Comments |
|---|---|---|
TreeNode |
System .Assembly |
Assembly é a primeira classe a ser usada quando um programa em C# deve coletar informações de reflexão. Métodos estáticos na classe TreeNode X++ são o ponto de partida para reflexão em X++. |
TreeNode |
System .Type |
Os métodos de instância correspondem TreeNode aos métodos de instância em System.Type. |
TreeNode .AOTgetSource |
MethodInfo |
O AOTgetSource método retorna várias informações juntas em uma cadeia de caracteres. Isso inclui o código-fonte X++ no método. Por outro lado, MethodInfo tem um membro separado para cada informação. |
TreeNode .AOTfirstChild
TreeNode .AOTnextSibling
TreeNode .AOTiterator
AOTiterator
|
MethodInfo[] (uma matriz) | Em C#, o GetMethods método em System.Type retorna uma matriz de objetos MethodInfo. Você pode fazer loop pela matriz pela técnica comum de incrementar um indexador. Por outro lado, o modelo X++ é navegar pelo controle de árvore do AOT. Os TreeNode métodos de AOTfirstChild e AOTnextSibling realizar a navegação. Como alternativa equivalente, a classe X++ AOTiterator foi projetada para navegar pelo controle de árvore do AOT. Um nó de classe é o pai em vários nós de método. As AOTiterator etapas por meio de nós filho, retornando cada um como outra TreeNode instância. Recursos adicionais dos TreeNode métodos nomeados AOTparent e AOTprevious. |
TreeNode .AOTgetProperty
TreeNode .AOTgetProperties
TreeNode .AOTname
|
PropertyInfo |
Em X++, o AOTgetProperties método retorna uma cadeia de caracteres longa que contém pares nome-valor para todas as propriedades do TreeNode. O AOTname método retorna uma cadeia de caracteres que contém apenas o valor da propriedade name. |
TreeNode .AOTsave
TreeNode .AOTinsert
|
System .Reflection .Emit (namespace de classes) |
O AOTsave método aplica alterações de um TreeNode objeto em seu código X++ ao AOT e as alterações são mantidas. Para obter um exemplo de código grande, consulte o Método TreeNode.AOTsave. |
Comparação: Classes sobre E/S de Arquivo
Há várias classes que executam operações de E/S (entrada e saída) de arquivo. No .NET Framework usado em C#, os equivalentes a essas classes residem no System.IO namespace.
A tabela a seguir lista várias classes do .NET Framework para C# que estão no System.IO namespace. Cada linha na tabela mostra a classe X++ ou o método que melhor corresponde à classe .NET Framework.
| X++ | C# | Comments |
|---|---|---|
BinaryIo |
FileStream
BinaryReader
BinaryWriter
|
Classes X++, como BinaryIo as que se estendem da classe Io abstrata, servem como um fluxo e também servem como leitor e gravador para esse fluxo. Em C#, o fluxo é uma classe separada da classe que tem métodos de leitura e gravação mais específicos. |
TextBuffer |
MemoryStream |
Essas classes contêm um buffer na memória e alguns dos métodos tratam o buffer como se fosse um arquivo no disco rígido. |
| WINAPI::createDirectory WINAPI::folderExists WINAPI::removeDirectory |
Directory
DirectoryInfo
Path
|
O X++ pode usar métodos estáticos na classe para muitas funções básicas do WINAPI sistema operacional que envolvem diretórios. |
| WINAPI::getDriveType |
DriveInfo
DriveType
|
Essas classes e métodos são usados para obter informações relacionadas à unidade. |
| WINAPI::copyFile WINAPI::createFile WINAPI::d eleteFile WINAPI::fileExists |
File
FileAttributes
FileInfo
|
O X++ pode usar métodos estáticos na classe para muitas funções básicas do WINAPI sistema operacional que envolvem arquivos. |
CommaIo
Comma7Io
|
(Nenhuma classe correspondente.) | Essas classes X++ podem gerar arquivos que o Microsoft Excel pode importar. No X++, uma referência de biblioteca epplus está disponível para interação adicional com o Excel. |
AsciiIo
TextIo
|
FileStream
TextReader
TextWriter
|
Essas classes usam páginas de código diferentes. |
Io |
Stream
StreamReader
StreamWriter
FileStream
|
Geralmente, elas são usadas como classes base que outras classes estendem. |
CodeAccessPermission
FileIoPermission
|
System.Security
.CodeAccessPermission O namespace System.Security.Permissions inclui as seguintes classes:
|
Os conceitos e métodos de assert, demande revertAssert se aplicam a ambos os idiomas. No entanto, os métodos e deny disponíveis revertDeny em C# não estão disponíveis no X++. |
Comparação de SQL X++, ANSI: Seleção de SQL
Em X++, a sintaxe de instrução de seleção do SQL difere da especificação ANSI (American National Standards Institute).
Seleção de Tabela Única
A tabela a seguir lista as diferenças entre as instruções selecionadas do SQL X++ e do SQL ANSI.
| Característica | X++ SQL | ANSI SQL | Comments |
|---|---|---|---|
| Nome da tabela na cláusula from . | A cláusula from lista uma instância de buffer de registro declarada de uma tabela, como da CustTable tabela. |
A cláusula from lista um nome de tabela, não o nome de um buffer. | O buffer de registro tem todos os métodos que a xRecordclasse tem em X++. |
| Sequência de sintaxe da ordem em comparação com as cláusulas de onde . | A ordem por cláusula deve aparecer antes da cláusula where . A ordem por cláusula deve aparecer após a cláusula from ou join . A cláusula group by deve seguir as mesmas regras de posicionamento de sintaxe que a ordem segue. | A ordem por cláusula deve aparecer após a cláusula where . A cláusula where deve aparecer após a cláusula from ou join . | No SQL X++ e ANSI, as cláusulas de entrada e junção devem aparecer antes da ordem por e onde as cláusulas. |
| Negação de condição. | O ponto de exclamação ('!') é usado para negação. | A palavra-chave não é usada para negação. | O X++ não dá suporte à sintaxe !like. Em vez disso, você deve aplicar o ! operador para uma cláusula. |
| Caracteres curinga para o operador semelhante . | 0 a muitos – Asterisco ('*') Exatamente 1 – Ponto de interrogação ('?') |
0 a muitos – Sinal de porcentagem ('%') Exatamente 1 – Barra inferior ('_') |
|
| Operadores lógicos na cláusula where . | E – && Ou – || |
E – e Ou – ou |
Exemplo de código
O exemplo de código a seguir ilustra os recursos na tabela anterior.
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
***/
Palavras-chave do SQL X++
As seguintes palavras-chave do SQL X++ estão entre as que não fazem parte do SQL ANSI:
- crosscompany
- firstonly100
- forceliterals
- forcenestedloop
- forceplaceholders
- forceselectorder
- validtimestate
Cláusula Join
A tabela a seguir lista as diferenças sobre a palavra-chave de junção do SQL X++ e do SQL ANSI.
| Característica | X++ SQL | ANSI SQL | Comments |
|---|---|---|---|
| Lista de colunas. | As colunas na lista de colunas devem vir todas da tabela listada na cláusula from e não de nenhuma tabela em uma cláusula de junção . As colunas na lista não podem ser qualificadas pelo nome da tabela. | As colunas na lista de colunas podem vir de qualquer tabela nas cláusulasde junção ou de entrada. Ele ajuda outras pessoas a manter seu código quando você qualifica as colunas na lista com o nome da tabela. | Para obter mais informações, consulte Selecionar Instruções em Campos. |
| Sintaxe da cláusula Join. | A cláusula join segue a cláusula where . | A cláusula join segue uma tabela na cláusula from . | No exemplo de código X++, os critérios de junção são uma igualdade de SalesPoolId valores. |
| Palavra-chave interna . | O modo de junção padrão é a junção interna. Não há uma palavra-chave interna . | O modo de junção padrão é a junção interna. A palavra-chave interna está disponível para tornar o código explícito. | A palavra-chave externa existe no SQL X++ e no SQL ANSI. |
| Palavras-chave esquerda e direita . | As palavras-chave esquerda e direita não estão disponíveis. Todas as junções são deixadas. | As palavras-chave esquerda e direita estão disponíveis para modificar a palavra-chave join . | Sem comentários. |
| Operador de igualdade. | O operador de sinal de igual duplo (''==) é usado para testar a igualdade de dois valores. |
O operador de sinal de igual único (''=) é usado para testar a igualdade de dois valores. |
Sem comentários. |
Exemplo de código
O exemplo de código a seguir ilustra a sintaxe de junção no SQL X++.
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);
}
}
Campos de Agregação
A tabela a seguir lista algumas diferenças na forma como os campos de agregação na lista de colunas selecionadas são referenciados entre o SQL X++ e o SQL ANSI. Campos de agregação são aqueles derivados por funções como soma ou média.
| Característica | X++ SQL | ANSI SQL | Comments |
|---|---|---|---|
| Alias de nome de campo agregado. | O valor agregado está no campo que foi agregado. | Você pode usar a palavra-chave como para marcar um campo de agregação com um alias de nome. O alias pode ser referenciado no código subsequente. | Para obter mais informações, consulte funções de agregação: diferenças entre X++ e SQL |
Exemplo de código
No exemplo de código a seguir, a chamada para o método de informações ilustra a maneira de referenciar campos agregados (consulte 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.
***/
Outras diferenças
A tabela a seguir lista outras diferenças da instrução select entre o SQL X++ e o SQL ANSI.
| Característica | X++ SQL | ANSI SQL | Comments |
|---|---|---|---|
| A palavra-chave having . | Não há uma palavra-chave que tenha . | A palavra-chave having permite que você especifique critérios de filtro para linhas geradas pelo grupo por cláusula. | Sem comentários. |
| Resultados nulos. | Em uma instrução de seleção de tempo , se a cláusula where filtra todas as linhas, nenhuma linha de contagem especial será retornada para relatar isso. | Em uma seleção, se a cláusula where filtra todas as linhas, uma linha de contagem especial é retornada. O valor da contagem é 0. | Sem comentários. |
| Cursores para navegar em linhas retornadas. | A instrução while select fornece funcionalidade de cursor. A alternativa é usar a próxima palavra-chave. | Você pode declarar um cursor para fazer loop pelas linhas retornadas de uma instrução select . | |
| Da cláusula. | A palavra-chave a partir é opcional quando nenhuma coluna é listada e apenas uma tabela é referenciada. As duas opções de sintaxe a seguir são equivalentes: select \* from tCustTable; select tCustTable; |
Uma instrução select não pode ler de uma tabela, a menos que a cláusula from seja usada. | No SQL X++, a instrução seleção simples preenche a variável de buffer de tabela com a primeira linha retornada. Isso é ilustrado pelo seguinte fragmento de código: select \* from tCustTable; info(tCustTable.Name); |