【问题标题】:Can I Have Unnamed Dynamic Array Types as Var Parameters我可以将未命名的动态数组类型作为 Var 参数吗
【发布时间】:2009-10-30 21:19:08
【问题描述】:

使用 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 参数识别为动态数组而不是开放数组,以便调用者可以声明一个简单的“整数数组”而不是一些命名的输入?

提前致谢。

【问题讨论】:

  • 你为什么想要/需要?这是标准的 Pascal 用法。您需要做的就是将“a”声明为:TIntArray。如果您正在处理遗留代码,则无论如何都需要对其进行更改(以添加对 SizeArray 的调用)我假设 SizeArray 只是一个示例 - 否则为什么不直接调用 SetLength>
  • 强制调用者使用命名类型有效,但这不是我的偏好。我想要一些不需要它并且可以接受简单的“X 数组”类型的东西。所以我想我会问一下,看看是否可以做到。
  • 调用者使用正确的类型真的没什么大不了的。你一直都在使用记录和类类型,那么为什么不使用其他结构化类型呢?而且这是程序员很快就会发现的要求,因为否则代码将无法编译,所以这不像您要放入一些定时炸弹,直到产品即将交付使用时才会爆炸。只要确保使用 RTL 提供的类型(如果有的话),而不是自己编写声明。

标签: delphi delphi-2010


【解决方案1】:

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;

...因此它可以为任意动态数组提供名称。

【讨论】:

  • 我没有注意到 System.那很好。我认为养成以这种方式声明数组的习惯会很有用。起初我认为 System 中的 TArray 与 Generics.Collections 中的 TArray 冲突,但我想它不是因为那个不是泛型的。这是一个很好的解决方案。谢谢。
【解决方案2】:

这确实是可能的......只需使用绝对关键字和无类型变量。

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;

【讨论】:

  • +1 表示非常聪明。我已经开始了巴里凯利的道路,所以我接受他的回答。但是,为了找到一种方法……我印象深刻。 :)
【解决方案3】:

不,没有办法做到这一点。它是 Pascal 语言规范的一部分,不太可能改变。

编辑:Skamradt 找到了一种方法。让我重申一下。没有办法做到这一点安全。

【讨论】:

  • 啊,但是没有 Rails 的编程会增加一点肾上腺素。 ...哦,等等,那是最后一轮通宵调试的震动可乐。 :)
  • 我一直都在不使用 Rails 进行编程。老实说,从来都不是 Ruby 的忠实粉丝...... ;)
猜你喜欢
  • 1970-01-01
  • 2021-09-15
  • 1970-01-01
  • 1970-01-01
  • 2014-07-09
  • 2018-10-11
  • 1970-01-01
  • 2014-11-02
  • 1970-01-01
相关资源
最近更新 更多