Drop the parentheses from the case false of value sets

Applies NKarolak's review suggestion: a case value set needs no parentheses
around a comparison.

Encodes the rationale in the Best Practice section, since it is a real
advantage of the pattern and is not documented elsewhere in the repo. The AL
operator hierarchy places and/xor above the comparison operators and or just
above them too, so parentheses are mandatory in an and chain — A = B and
C = D misparses without them — while a case value set has no and to bind
tighter and needs none. That inverts the precedence most developers arrive
with from C#.

Also notes in the bad sample that its parentheses are not optional, so the
two samples contrast on parentheses as well as on evaluation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
António Silva 2026-08-27 10:31:00 +01:00
parent 580970ac12
commit 0d5150c47b
3 changed files with 7 additions and 6 deletions

View file

@ -21,7 +21,8 @@ codeunit 50543 "Perf Sample CaseChain Bad"
begin
// The wrong escape from the ladder: flattening it into 'and' trades the
// nesting for a defect, because every operand is still evaluated. Item
// fields are read even when the Get failed.
// fields are read even when the Get failed. The parentheses are not
// optional either — 'and' binds tighter than '=' and '<>' in AL.
exit((SalesLine.Type = SalesLine.Type::Item) and (SalesLine."No." <> '') and
(SalesLine."Qty. to Ship" > 0) and Item.Get(SalesLine."No.") and (not Item.Blocked));
end;

View file

@ -8,11 +8,11 @@ codeunit 50542 "Perf Sample CaseChain Good"
// so each condition is reached only when the previous one passed — and
// Item.Get is never called for a non-item line.
case false of
(SalesLine.Type = SalesLine.Type::Item),
(SalesLine."No." <> ''),
(SalesLine."Qty. to Ship" > 0),
SalesLine.Type = SalesLine.Type::Item,
SalesLine."No." <> '',
SalesLine."Qty. to Ship" > 0,
Item.Get(SalesLine."No."),
(not Item.Blocked):
not Item.Blocked:
exit(false);
end;
exit(true);

View file

@ -15,7 +15,7 @@ Because AL gives no short-circuit guarantee for `and` and `or`, a chain of condi
## Best Practice
Sequence two or three dependent conditions with nested `if`. Beyond that, switch to `case`: use `case false of` for a chain of guards where every condition must hold, letting control fall past `end` when all of them pass; use `case true of` for first-match dispatch, where each later probe runs only if the earlier ones did not match. Conditions that share an action are comma-separated into a single value set, one per line, so the chain reads as one ordered list with one failure action instead of repeating that action per condition. This keeps every condition at one indentation level, makes evaluation order explicit rather than implied by nesting, and preserves the stop-at-first-match behaviour. It also aligns with the AL programming convention that more than two alternatives belong in a `case` statement rather than an `if-then-else`.
Sequence two or three dependent conditions with nested `if`. Beyond that, switch to `case`: use `case false of` for a chain of guards where every condition must hold, letting control fall past `end` when all of them pass; use `case true of` for first-match dispatch, where each later probe runs only if the earlier ones did not match. Conditions that share an action are comma-separated into a single value set, one per line, so the chain reads as one ordered list with one failure action instead of repeating that action per condition. A value set also needs no parentheses around a comparison, unlike an operand of `and` or `or`: the AL operator hierarchy places `and` and `or` above the comparison operators, so parentheses are mandatory there and the chain fills up with them. This keeps every condition at one indentation level, makes evaluation order explicit rather than implied by nesting, and preserves the stop-at-first-match behaviour. It also aligns with the AL programming convention that more than two alternatives belong in a `case` statement rather than an `if-then-else`.
See sample: `case-true-of-for-long-condition-chains.good.al`.