Usar instruções repetitivas
Você pode usar instruções repetitivas quando desejar repetir a implementação de uma ou mais instruções. Os cinco tipos diferentes de instruções repetitivas que você pode usar são:
for-to-do
for-downto-do
foreach-in-do
while-do
repeat-until
Instrução For
Uma das instruções repetitivas mais usadas é a instrução for. Se você usar a instrução for, já deve saber quantas vezes a implementação das instruções será repetida.
No próximo exemplo, a instrução for é usada para um loop de cinco vezes. A variável intCount contará o número de vezes que você repetiu.
var
intCount: Integer;
total: Integer;
begin
for intCount := 1 to 5 do
total := total + 3;
end;
No exemplo a seguir, o número de loops é corrigido usando um número (como 5). Você também pode usar outra variável inteira em vez de um valor fixo. De qualquer maneira, a instrução for sabe, antecipadamente, quantos loops serão necessários.
var
intCount: Integer;
numberOfLoops: Integer;
total: Integer;
begin
numberOfLoops := 5;
for intCount := 1 to numberOfLoops do
total := total + 3;
end;
A instrução for só pode executar uma instrução. Se você quiser executar mais de uma instrução, precisará usar uma instrução composta com begin e end.
Instrução For downto
Com a instrução for, você está contando para cima, o que significa que a instrução for aumentará o valor da variável. Você também pode diminuir usando a instrução for downto, que conta para baixo.
Semelhante à instrução for, que só pode executar uma instrução, a instrução for downto só executa uma instrução. O próximo exemplo mostra a instrução composta que está sendo usada.
var
intCount: Integer;
totalSales: Integer;
numberSales: Integer;
sales: array[5] of Integer;
begin
GetSales(sales);
for intCount := 5 downto 1 do begin
totalSales := totalSales + sales[intCount];
numberSales := numberSales + 1;
end;
end;
Instrução Foreach
A instrução foreach só pode ser usada em coleções Enumerable (List of e Dictionary of), e não pode ser usada com matrizes.
Com a instrução foreach, a variável receberá o valor de um determinado item nas coleções. Cada loop será atribuído ao próximo valor.
var
stringList: List of [Text[20]];
stringItem: Text[20];
begin
foreach stringItem in stringList do
Message(stringItem);
end;
Instrução While
A instrução while verifica primeiro se a condição é verdadeira antes de iniciar o loop. Se essa condição for verdadeira, ela continuará executando as instruções no seu bloco while.
Portanto, será possível que as instruções não sejam executadas se a condição não for true na primeira vez.
var
index: Integer;
totalSales: Integer;
sales: array[5] of Integer;
begin
GetSales(sales);
while totalSales < 8 do begin
index := index + 1;
totalSales := totalSales + sales[index];
end;
end;
Se você quiser executar várias instruções, precisará usar uma instrução composta.
Instrução Repeat until
A instrução while verifica primeiro se há uma condição válida antes de iniciar o loop, enquanto a instrução repeat until vai ser executada primeiro e, depois, verificar se há uma condição. Ela fará um loop até que a condição seja válida, o que significa que as instruções repeat until são, no mínimo, executadas uma vez. O loop continuará, se a condição não for válida.
A instrução repeat until é uma instrução única, e você coloca suas próprias instruções no bloco. Essa característica significa que você não precisará usar uma instrução composta se quiser executar várias instruções.
var
index: Integer;
totalSales: Integer;
sales: array[5] of Integer;
begin
GetSales(sales);
repeat
index := index + 1;
totalSales := totalSales + sales[index];
until totalSales >= 8;
end;
Geralmente, a instrução repeat until é usada quando você deseja executar um loop sobre um conjunto de registros. No próximo exemplo, você fará um loop sobre todas as linhas da tabela MyTable.
var
myTable: Record MyTable;
begin
myTable.FindSet();
repeat
myTable.Amount := 100;
until myTable.Next() = 0;
end;
Instrução With
A instrução with às vezes é usada em combinação com uma instrução repetitiva, mas também pode ser usada de maneira autônoma. A finalidade da instrução with é reduzir o uso das suas variáveis de registro. Essa estrutura é ilustrada no exemplo a seguir, onde uma variável myTable é criada, e os campos na tabela são todos atribuídos com um valor.
var
myTable: Record MyTable;
begin
myTable."No." := 1;
myTable.Amount := 100;
myTable.Credits := 10;
myTable."Document Type" := myTable."Document Type"::Invoice;
myTable.Reason := myTable.Reason::Return;
myTable.Refund := 100;
end;
Em vez de digitar novamente a palavra myTable, você pode usar a instrução with.
var
myTable: Record MyTable;
begin
with myTable do begin
"No." := 1;
Amount := 100;
Credits := 10;
"Document Type" := "Document Type"::Invoice;
Reason := Reason::Return;
Refund := 100;
end;
end;
Preterir as instruções with explícitas e implícitas
O modelo de extensibilidade e a linguagem de programação AL são sucessores da linguagem C/AL. E até agora, a instrução with era permitida em AL.
Usar a instrução with pode dificultar a leitura do código. Ele também pode impedir que o código em Business Central seja atualizado sem alterações no código ou ainda pior - atualizado, mas com comportamento alterado.
Nós consideramos dois tipos diferentes de instruções with: o tipo explícito com uso de palavra-chave e o tipo implícito que não é expresso diretamente no código. As próximas seções descrevem cada uma dessas instruções.
Instruções with explícitas
No Business Central Online, seu código é recompilado quando as versões da plataforma e do aplicativo são atualizadas. A recompilação garante que ela funcione e regenera os artefatos de runtime para que correspondam à nova plataforma. Não são permitidas alterações da falha sem o devido aviso, mas o uso da instrução with impossibilita, como a Microsoft, fazer alterações aditivas de modo completamente sem falha. Esse problema não é isolado das alterações feitas pela Microsoft. Qualquer alteração aditiva tem o potencial de falhar uma instrução with no código de consumo.
O exemplo a seguir ilustra o código escrito com a instrução with, chamado neste contexto de instrução with explícita:
codeunit 50140 MyCodeunit
{
procedure DoStuff()
var
Customer: Record Customer;
begin
with Customer do begin
// Do some work on the Customer record.
Name := 'Foo';
if IsDirty() then
Modify();
end;
end;
local procedure IsDirty(): Boolean;
begin
exit(false);
end;
}
O procedimento DoStuff() processa o trabalho no registro de Customer e chama um procedimento local IsDirty() para verificar se deve ou não atualizar o registro. Observando o código anterior, parece que ele não faz nada, já que IsDirty() retorna falso, supondo que a chamada IsDirty() (linha 11) esteja de fato chamando o procedimento IsDirty() local.
Pesquisas de símbolos
Considerando novamente o exemplo de código anterior, o que aconteceria com esse código se IsDirty fosse adicionado ao aplicativo base entre duas liberações? Para entender isso, precisamos examinar como os compiladores transformam a sintaxe em símbolos. Quando o compilador AL atende à chamada IsDirty, ele deve associar o nome da sintaxe a um símbolo do procedimento.
Quando o compilador AL pesquisa o símbolo IsDirty() no exemplo anterior, ele pesquisa na seguinte ordem:
1 – tabela Customer
Membros definidos pelo usuário na tabela Customer e nas extensões da tabela Customer
Membros definidos pela plataforma, por exemplo, FindFirst() ou Modify()
2 – Codeunit MyCodeunit
- Membros definidos pelo usuário, por exemplo, IsDirty()
- Membros definidos pela plataforma
3 – Membros definidos globalmente
Quando a pesquisa por IsDirty encontrar o nome IsDirty pela primeira vez, ela não prosseguirá para próximo grupo de nível superior. Isso significa que, se um procedimento chamado IsDirty for introduzido na tabela Customer, (plataforma ou aplicativo), esse procedimento será encontrado no lugar do procedimento em MyCodeunit.
A solução para o with explícito é parar de usá-lo. O uso da instrução with pode tornar seu código vulnerável a alterações de upstream. O exemplo a seguir ilustra como reescrever o exemplo usando a instrução with explícita.
// Safe version
codeunit 50140 MyCodeunit
{
procedure DoStuff()
var
Customer: Record Customer;
begin
// Do some work on the Customer record.
Customer.Name := 'Foo';
if IsDirty() then
Customer.Modify();
end;
local procedure IsDirty(): Boolean;
begin
exit(false);
end;
}
Instrução with implícita
O with implícito é inserido automaticamente pelo compilador em determinadas situações. As seções a seguir descrevem como isso funciona nas codeunits e nas páginas.
Codeunits
Quando uma codeunit tem a propriedade TableNo definida, o código dentro do gatilho OnRun é colocado entre with implícito. Isso é indicado pelos comentários no exemplo de código abaixo.
codeunit 50140 MyCodeunit
{
TableNo = Customer;
trigger OnRun()
begin
// with Rec do begin
SetRange("No.", '10000', '20000');
if Find() then
repeat
until Next() = 0;
if IsDirty() then
Error('Something is not clean');
// end;
end;
local procedure IsDirty(): Boolean;
begin
exit(false);
end;
}
De forma semelhante à Instrução with explícita, o código parece chamar o método local IsDirty. Mas, dependendo da tabela Customer, extensões para a tabela Customer e métodos internos, esse pode não ser o caso. Se qualquer um deles implementar um método IsDirty com uma assinatura idêntica que retorne verdadeiro, o exemplo acima falhará com um erro. Se um método IsDirty com uma assinatura diferente for implementado, esse código não será compilado e não poderá ser atualizado.
Páginas
As páginas nas tabelas têm o mesmo tipo de with implícito, mas envolvendo o objeto inteiro. Em qualquer lugar dentro do objeto de página, os campos e os métodos das tabelas de origem estão diretamente disponíveis sem nenhum prefixo.
page 50143 ImplicitWith
{
SourceTable = Customer;
layout
{
area(Content)
{
field("No."; "No.") { }
field(Name; Name)
{
trigger OnValidate()
begin
Name := 'test';
end;
}
}
}
trigger OnInit()
begin
if IsDirty() then Insert()
end;
local procedure IsDirty(): Boolean
begin
exit(Name <> '');
end;
}
Nas páginas, não é apenas o código nos gatilhos e procedimentos que está incluído no with implícito no registro de origem, as expressões de origem dos campos também são abordadas.
Com ou sem with: isso não é uma questão
Neste repositório GitHub, você pode encontrar mais exemplos e códigos: BCTech/samples/WithOrWithout/
Instrução break
Se desejar interromper a execução de um loop, poderá usar a instrução break.
var
intCount: Integer;
total: Integer;
begin
for intCount := 1 to 5 do begin
if (total > 8) then
break;
total := total + 3;
end;
end;