mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-10-05 14:46:55 +01:00
Forslag: var-parametre kraever en adresserbar variabel, ikke literal/udtryk
This commit is contained in:
parent
02f0d49654
commit
bed13b9b60
1 changed files with 63 additions and 0 deletions
|
|
@ -0,0 +1,63 @@
|
||||||
|
---
|
||||||
|
bc-version: [all]
|
||||||
|
domain: style
|
||||||
|
keywords: [var-parameter, by-reference, pass-by-reference, literal, constant, compile-error, procedure-call]
|
||||||
|
technologies: [al]
|
||||||
|
countries: [w1]
|
||||||
|
application-area: [all]
|
||||||
|
---
|
||||||
|
|
||||||
|
# A `var` parameter must be called with a variable, never a literal or expression
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
When a procedure declares a parameter with `var` — `procedure DoSomething(var Result: Text)` —
|
||||||
|
that parameter is passed by reference: the callee writes back into the
|
||||||
|
caller's own memory location. This means the argument at the call site
|
||||||
|
must be an actual variable, something with an address. A string literal, a
|
||||||
|
numeric constant, or a computed expression has no address to write back
|
||||||
|
to, so passing one to a `var` parameter fails to compile.
|
||||||
|
|
||||||
|
This is a known failure mode when generating AL code without tracking
|
||||||
|
which parameters on a called procedure are declared `var`: a call that
|
||||||
|
would be valid for a by-value parameter (`DoSomething('Hello')`,
|
||||||
|
`DoSomething(SomeText + Suffix)`) is invalid the moment that same parameter
|
||||||
|
position is `var`. Before writing a call, check the callee's signature for
|
||||||
|
`var` on each parameter position being supplied a literal or expression —
|
||||||
|
if present, a variable declared in the caller's own scope must be used
|
||||||
|
instead, even if that means declaring a throwaway local variable just to
|
||||||
|
hold the value.
|
||||||
|
|
||||||
|
## Best Practice
|
||||||
|
|
||||||
|
```al
|
||||||
|
procedure GetCustomerName(CustomerNo: Code[20]; var Name: Text[100])
|
||||||
|
begin
|
||||||
|
if Customer.Get(CustomerNo) then
|
||||||
|
Name := Customer.Name;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
CustName: Text[100];
|
||||||
|
...
|
||||||
|
GetCustomerName('10000', CustName);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Anti Pattern
|
||||||
|
|
||||||
|
```al
|
||||||
|
procedure GetCustomerName(CustomerNo: Code[20]; var Name: Text[100])
|
||||||
|
begin
|
||||||
|
if Customer.Get(CustomerNo) then
|
||||||
|
Name := Customer.Name;
|
||||||
|
end;
|
||||||
|
...
|
||||||
|
GetCustomerName('10000', 'placeholder'); // compile error: cannot pass a literal to a var parameter
|
||||||
|
GetCustomerName('10000', CustName + ''); // compile error: an expression is not addressable either
|
||||||
|
```
|
||||||
|
|
||||||
|
Both anti-pattern calls fail to compile with an error to the effect of "a
|
||||||
|
`var` parameter requires a variable" — the fix is always to declare (or
|
||||||
|
reuse) a variable for that argument position, never to reach for a literal
|
||||||
|
or expression because the value "looks" like what the parameter should
|
||||||
|
receive.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue