Use a single exit(false) for the whole case false of chain

Review decision: all five conditions share one action, so they share one
comma-separated value set with a single exit(false).

Aligns the article's Best Practice with the sample — it previously told
authors to keep side-effecting conditions in their own value set, which the
sample no longer does — and drops the now-contradictory wording about listing
the failure action per condition.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
António Silva 2026-08-25 14:52:44 +01:00
parent f7a00bf0b6
commit 580970ac12
2 changed files with 6 additions and 14 deletions

View file

@ -4,22 +4,14 @@ codeunit 50542 "Perf Sample CaseChain Good"
var
Item: Record Item;
begin
// 'case false of' matches the value sets in order and stops at the first
// match, so each value set is reached only when the previous one passed —
// and Item.Get is never called for a non-item line.
// 'case false of' matches the values in order and stops at the first match,
// 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
// Pure field reads with no side effects and no order dependency, so
// they share one value set and one action.
(SalesLine.Type = SalesLine.Type::Item),
(SalesLine."No." <> ''),
(SalesLine."Qty. to Ship" > 0):
exit(false);
// These two keep their own value sets even though the action repeats:
// ordering across separate value sets is what the documentation
// guarantees. The Get must not run until the checks above pass, and
// Blocked must not be read until the Get succeeded.
Item.Get(SalesLine."No."):
exit(false);
(SalesLine."Qty. to Ship" > 0),
Item.Get(SalesLine."No."),
(not Item.Blocked):
exit(false);
end;

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, listing the failure action per condition and letting control fall past `end` when all pass; use `case true of` for first-match dispatch, where each later probe runs only if the earlier ones did not match. Value sets that share an action may be comma-separated into one value set, but only when each is a pure, order-independent test — a field comparison or an enum check. A condition with a side effect, or one that is only safe after an earlier condition passed, keeps its own value set even when its action repeats, because ordered matching is guaranteed *across* value sets, not within one. 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. 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`.