Can I Have Unnamed Dynamic Array Types as Var Parameters
-
22-07-2019 - |
Question
Using D2010, I'd like to do something like this:
procedure SizeArray(var aArr: array of integer; aSize: integer);
begin
SetLength(aArr,aSize);
end;
But this fails to compile. Because my "aArr" parameter isn't a dynamic array, it's an open array parameter. And SetLength cannot be called on it. The only way I know of to force the parameter to be a dynamic array is to give it a type name, like so:
type
TIntArray = array of integer;
procedure SizeArray(var aArr: TIntArray; aSize: integer);
begin
SetLength(aArr,aSize);
end;
And now the code compiles. And it works fine, for the most part, but this fails:
procedure Test;
var
a : array of integer;
begin
SizeArray(a,5);
end;
Because types of actual and formal var parameters must be identical and the compiler doesn't recognize "array of integer" and "TIntArray" as identical types.
So, here's my question: Is there some way I can get the compiler to identify my var parameter as a dynamic array rather than as an open array so that the caller can declare a simple "array of integer" rather than some named type?
Thanks in advance.
Solution
Pascal, and by extension Delphi, uses name equivalence rather than structural equivalence for array types, including dynamic arrays. Variables declared with a type that doesn't have a name, like this:
var
x: array of Integer;
... end up using an anonymous name that isn't equivalent to any other type's name. That's why you get the error. The error can be useful; for example, consider an array of Kilometers
vs an array of Kilograms
- but it's often the case that declaring a name for every distinct type is inconvenient.
To get around this issue, and staying within the safe type system (so avoiding untyped parameters, as skamradt suggests), I recommend using the same name for every particular array shape. You can do this to a reasonably large degree by using the TArray<T>
type declared in the System unit. So, instead of working with array of Integer
, use TArray<Integer>
.
TArray<T>
is declared like this:
type
TArray<T> = array of T;
... so it can supply a name for arbitrary dynamic arrays.
OTHER TIPS
This is indeed possible...just use the absolute keyword along with an untyped var.
procedure SizeArray(var aArr; aSize: integer);
var
ActArr : Array of Integer absolute aArr;
begin
SetLength(ActArr,aSize);
end;
var
Test : Array of Integer;
begin
SizeArray(Test,5);
showMessage(IntTostr(High(Test))); // -- returns 4
end;
No, there's no way to do that. It's part of the Pascal language specification and isn't likely to change.
EDIT: Skamradt found a way. Let me restate that. There's no way to do that safely.