@ works on a property that reads a field - is the DocWiki page wrong?

The DocWiki page “Properties (Delphi)” says: “Unlike fields, properties cannot be passed as var parameters, nor can the @ operator be applied to a property.”

I tested it on Delphi 13 (Win32) and I disagree with the second half.

type
TOwned = class
end;

TTest = class
private
FCount: Integer;
FOwned: TOwned;
function GetCalc: Integer;
function GetOwned: TOwned;
public
constructor Create;
procedure TakeAddressInside;
property Count : Integer read FCount; { field-backed }
property Calc : Integer read GetCalc; { getter-backed }
property Owned : TOwned read FOwned; { field-backed object }
property OwnedG: TOwned read GetOwned; { getter-backed object }
end;

This compiles, and P points to FCount:

property Count: Integer read FCount; // no getter
…
P:= @Obj.Count;

With a getter (read GetCalc) I get “E2036 Variable required”, as the page says. The var half holds in both cases: “E2197 Constant object cannot be passed as var parameter”.

So for @, the compiler simply puts the field in place of the property. The page gives one reason for both rules: “a property doesn’t necessarily exist in memory”. That explains the getter case. It does not explain why @ is accepted on a property that reads a field, while var is refused.

The same substitution decides what FreeAndNil does (it takes const [ref]). The 10.4 release notes say that FreeAndNil on a property sets only a temporary variable to nil. In my test, that is true only with a getter. FreeAndNil(Obj.Owned) sets FOwned to nil. But if Owned reads through a getter, the call compiles with no warning, frees the object, and FOwned still points to the freed object.

So, my questions: is that DocWiki sentence simply outdated, or do I miss a case where @ on the property and @ on its field give different results? And is there a real reason why var is refused when @ is not?

1 Like