Могу ли я иметь безымянные типы динамических массивов в качестве параметров Var - PullRequest
3 голосов
/ 31 октября 2009

Используя D2010, я хотел бы сделать что-то вроде этого:

procedure SizeArray(var aArr: array of integer; aSize: integer);
begin
  SetLength(aArr,aSize);
end;

Но это не скомпилировать. Поскольку мой параметр "aArr" не является динамическим массивом, это параметр открытого массива. И 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 как динамический массив, а не как открытый массив, чтобы вызывающая сторона могла объявлять простой «целочисленный массив», а не какой-то именованный тип

Заранее спасибо.

Ответы [ 3 ]

10 голосов
/ 31 октября 2009

Pascal и, как следствие, Delphi, используют эквивалентность имен, а не структурную эквивалентность для типов массивов, включая динамические массивы. Переменные, объявленные с типом, у которого нет имени, например:

var
  x: array of Integer;

... в конечном итоге использовать анонимное имя, которое не эквивалентно имени любого другого типа. Вот почему вы получаете ошибку. Ошибка может быть полезной; например, рассмотрим массив Kilometers против массива Kilograms - но часто бывает так, что объявление имени для каждого отдельного типа неудобно.

Чтобы обойти эту проблему и остаться в системе безопасных типов (избегая нетипизированных параметров, как предлагает skamradt), я рекомендую использовать одно и то же имя для каждой конкретной формы массива. Вы можете сделать это в достаточно большой степени, используя тип TArray<T>, объявленный в системном блоке. Поэтому вместо работы с array of Integer используйте TArray<Integer>.

TArray<T> объявлено так:

type
  TArray<T> = array of T;

... чтобы он мог предоставить имя для произвольных динамических массивов.

9 голосов
/ 31 октября 2009

Это действительно возможно ... просто используйте абсолютное ключевое слово вместе с нетипизированной переменной.

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;
0 голосов
/ 31 октября 2009

Нет, это невозможно сделать. Это часть спецификации языка Pascal и вряд ли изменится.

РЕДАКТИРОВАТЬ: Скамрадт нашел способ. Позвольте мне повторить это. Там нет никакого способа сделать это безопасно.

...