A word about ‘out’ parameters in Delphi

Delphi compiler has a contract – any interface variable should be either a valid reference or nil. The same also applies to other lifetime managed types – strings and dynamic arrays. An interesting consequence of the contract is how Delphi interprets ‘out’ function parameters.
As the name suggests, ‘out’ means that an input value of a parameter should be ignored inside a function; but Delphi compiler cannot ignore input value of a lifetime managed instance. It decrements the reference count of an instance when an instance is no longer needed if a reference to instance is not nil.
As a workaround Delphi compiler applies the following trick. Suppose we have a procedure

procedure Foo(out II: IInterface);
begin
  II:= TInterfacedObject.Create;
end;

a call of the procedure

  Foo(II);

compiles as:

II:= nil;
Bar(II);

where

procedure Bar(var II: IInterface);
begin
  II:= TInterfacedObject.Create;
end;

Bar procedure decrements the reference count of the input parameter instance; the meaning of ‘out‘ parameter forbids to do so. Since Delphi compiler cannot ignore input value of a lifetime manage instance the problem was solved by assigning nil value to a parameter before calling a procedure.

About these ads

5 thoughts on “A word about ‘out’ parameters in Delphi

    • Documentation is poor as usual. Out counts only for lifetime managed types – otherwise it is an alias for var. At least it is so for Delphi XE.

      • I just wanted to say, I’ve always understood the meaning of “out” as “discards input”, rather than “ignores input”, clearly different from “var”. (I found your interpretation surprising.) You could also look at “ignoring input” as a special case of “discarding input” for non-managed types.

      • Well if you read documentation further you see “The call to GetInfo immediately frees the memory used by MyRecord, before program control passes to the procedure” which is simply untrue. I suppose ‘discard’ means something done with the data, but in this sense the data is ‘discarded’ only for lifetime managed types. For the other types nothing happens with the data passed as ‘out’ parameter, the same as with ‘var’ parameter.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s