Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I pass a var of type X to a open array parameter of that type?

Using Delphi XE-2 (all updates applied).

I would expect the following code to generate compilation errors on the DoSomething and DoInteger calls, but it doesn't.

program OpenArrayQuestion;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

type
  IComposite = interface(IInterface)
  ['{1AC3CF6A-1316-4838-B67B-9FB075585C1E}']
  end;

  IComposite<T: IComposite> = interface(IComposite)
  ['{7F866990-9973-4F8E-9C1F-EF93EF86E8F2}']
  end;

function DoSomething(const aData: array of IComposite): Boolean;
begin
  Result := True;
end;

function DoInteger(const aData: array of Integer): boolean;
begin
  Result := True;
end;

var
  FData: IComposite;
  FInteger: Integer;
begin
  DoSomething(FData);
  DoInteger(FInteger);
end.

Can somebody explain why I can pass FData/FInteger - both just single variables, to an open array parameter of their respective types without putting it between []'s and without the compiler barfing it right back at me?

I thought it might have to do with an array of interfaces, or even the generics involved, but the compiler accepts an integer passed to an open array of integer as well.

like image 992
Marjan Venema Avatar asked Nov 21 '12 09:11

Marjan Venema


1 Answers

The compiler is being a little lax because there is no ambiguity in doing so.

Consider the following:

program OpenArrays;

{$APPTYPE CONSOLE}

procedure Test1(i: Integer); overload;
begin
  Writeln('Test1Integer');
end;

procedure Test1(i: array of Integer); overload;
begin
  Writeln('Test1OpenArray');
end;

procedure Test2(i: array of Integer);
begin
  Writeln('Test2');
end;

var
  i: Integer;

begin
  Test1(i);
  Test1([i]);
  Test2(i);
  Readln;
end.

which produces this output:

Test1Integer
Test1OpenArray
Test2

I've overloaded Test1 so that there is a version that receives an integer, and a version that receives an open array of integers. In that situation, the call Test1(i) goes to the overload that receives just an integer. On the other hand, I can call Test2 which receives an open array, just by passing an integer.


I believe that this behaviour is not documented in the language guide. However, @hvd found the following in the documentation for compiler error E2192 (emphasis mine):

Open array arguments must be supplied with an actual array variable, a constructed array or a single variable of the argument's element type.

like image 99
David Heffernan Avatar answered Oct 02 '22 00:10

David Heffernan