Могу ли я иметь безымянные типы динамических массивов в качестве параметров Var
-
22-07-2019 - |
Вопрос
Используя D2010, я бы хотел сделать что-то вроде этого:
procedure SizeArray(var aArr: array of integer; aSize: integer);
begin
SetLength(aArr,aSize);
end;
Но это не компилируется. Потому что мой & Quot; aArr & Quot; Параметр не является динамическим массивом, это параметр открытого массива. И SetLength не может быть вызван на нем. Единственный известный мне способ заставить параметр быть динамическим массивом, это дать ему имя типа, например так:
type
TIntArray = array of integer;
procedure SizeArray(var aArr: TIntArray; aSize: integer);
begin
SetLength(aArr,aSize);
end;
А теперь код компилируется. И это работает нормально, по большей части, но это не удается:
procedure Test;
var
a : array of integer;
begin
SizeArray(a,5);
end;
Поскольку типы фактических и формальных параметров var должны быть идентичны, а компилятор не распознает " массив целых чисел " и " TIntArray " как идентичные типы.
Итак, вот мой вопрос: есть ли способ заставить компилятор идентифицировать мой параметр var как динамический массив, а не как открытый массив, чтобы вызывающая сторона могла объявить простой " массив целых чисел < !> Quot; а не какой-то именованный тип?
Заранее спасибо.
Решение
Pascal и, как следствие, Delphi, используют эквивалентность имен, а не структурную эквивалентность для типов массивов, включая динамические массивы. Переменные, объявленные с типом, который не имеет имени, например:
var
x: array of Integer;
... заканчиваются тем, что используют анонимное имя, которое не эквивалентно имени любого другого типа. Вот почему вы получаете ошибку. Ошибка может быть полезной; например, рассмотрим массив Kilometers
против массива Kilograms
- но часто бывает так, что объявление имени для каждого отдельного типа неудобно.
Чтобы обойти эту проблему и остаться в системе безопасных типов (избегая нетипизированных параметров, как предлагает skamradt), я рекомендую использовать одно и то же имя для каждой конкретной формы массива. Вы можете сделать это в достаточно большой степени, используя тип TArray<T>
, объявленный в системном блоке. Поэтому вместо работы с array of Integer
используйте TArray<Integer>
.
<=> объявлен так:
type
TArray<T> = array of T;
... чтобы он мог предоставить имя для произвольных динамических массивов.
Другие советы
Это действительно возможно ... просто используйте ключевое слово absolute вместе с нетипизированной переменной.
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;
Нет, это невозможно сделать. Это часть спецификации языка Pascal и вряд ли изменится.
РЕДАКТИРОВАТЬ: Скамрадт нашел способ. Позвольте мне повторить это. Невозможно сделать это безопасно.