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?