在Delphi中定义记录 - (记录为类型vs记录为变量) - 差异,缺点和优点......?

Tha*_*arc 4 arrays delphi record

我一直在研究Delphi中的记录,在大多数情况下我看到它们用作Type,然后声明它的一个新变量,例如:

type
  TMyRecord = record
    data1: sometype;
    data2: sometype;
  end;

var
  OnesRecord: TMyRecord;
Run Code Online (Sandbox Code Playgroud)

对于数组,它也用作:

type
  TMyRecord = record
    data1: sometype;
    data2: sometype;
  end;

var
  OnesRecord: array of TMyRecord;
Run Code Online (Sandbox Code Playgroud)

我的问题如下:

为什么不应该使用第一种方法用于数组,方式如下:

type
  TMyRecord = array of record
    data1: sometype;
    data2: sometype;
  end;

var
  OnesRecord: TMyRecord;
Run Code Online (Sandbox Code Playgroud)

另外,如果使用直接定义为变量的记录,例如:

var
  OnesRecord: record
    data1: sometype;
    data2: sometype;
  end;
Run Code Online (Sandbox Code Playgroud)

要么

var
  OnesRecord: array of record
    data1: sometype;
    data2: sometype;
  end;
Run Code Online (Sandbox Code Playgroud)

最后一件事; 如果要合并第二种和第三种方法,并且具有该类型的数组类型和该类型的数组的变量,它是否与具有数组的数组有什么不同?

那么,是这样的:

type
  TMyRecord = array of record
    data1: sometype;
    data2: sometype;
  end;

var
  OnesRecord: array of TMyRecord;
Run Code Online (Sandbox Code Playgroud)

与此不同的是:

type
  TMyRecord = record
    data1: sometype;
    data2: sometype;
  end;

var
  OnesRecord: array of array of TMyRecord;
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 5

这是一个非常简单的问题.这样写的时候

type
  TPoints = array of record
    X, Y: Double;
  end;
Run Code Online (Sandbox Code Playgroud)

您无法声明对数组的单个元素进行操作的变量或参数.如果您从不需要对单个项目进行操作,则上述声明可能是合理的.

你问题的每个方面在逻辑上都是一样的.是数组的数组,包含记录的记录,匿名记录和数组作为变量类型.问题和设计考虑因素是一样的.


这个问题或许有点主观.根据我的经验,使用如上所示的内联或匿名类型,往往是一个糟糕的选择.通常,在未来发展的某个时刻,很明显需要命名匿名类型.

所以我自己,我从不使用由匿名类型组成的复合类型.这样我总是能够重构代码以使用对单个元素进行操作的小方法.从来没有一个错误的限制推动我使用无法分解的复合类型的大型方法.

所以我将上面的类型声明为:

type
  TPoint = record
    X, Y: Double;
  end;
  TPoints = array of TPoint;
Run Code Online (Sandbox Code Playgroud)

虽然在现代Delphi中,出于类型兼容性的原因,省略TPoints和使用它会更好TArray<TPoint>.

  • 有时您只需要引用组成类型,因此必须更改代码以命名它.更阴险的是,如果你没有给选民命名,那么你就会被编写成比你想象的更大的方法.您可能希望应用提取方法重构但无法应用,因为无法命名所需的类型.所以你只是决定不提取方法.这是特别阴险的,因为你现在处于一个任意因素限制你编写干净的良好代码的愿望的位置. (3认同)

Dav*_*rtz 4

您所做的事情没有任何问题,就像没有什么可以阻止您重载 Add() 运算符来执行乘法一样。

你的问题完全是理论性的,所以很难以某种方式说出任何事情。是的,这些结构是“合法的”。所以呢?

这就像在您发现自己可以用手走路后询问用手走路还是用脚走路一样。

所有情况下的问题都是相同的......您为什么要这样做?

与其询问“合法”但没有人使用的编码方法,为什么不尝试展示一个例子来证明这种使用是一种优势呢?

从理论的角度来看,您正在尝试混搭两种不同的数据聚合机制。

数组是一种收集相同类型的项目的方法。记录和类是收集不同类型的相关项目的一种方式。它们都是某种容器,但具有不同的品质。

通常将数组声明为“array of”而不是“array of record ... end”。

按照约定,您将记录定义为 TYPE,以便您可以“重用”该类型。

显然您对此没有太多经验,因为您实际上无法在非常狭窄的设置之外使用这些构造。

假设您想定义类似“整数数组”的内容;您可以将其定义为特定类型:

type
 TIntArray = array of integer;
Run Code Online (Sandbox Code Playgroud)

你为什么要这样做?因为有时您会发现将两个不同的事物声明为“整数数组”会使它们不类型兼容,这是违反直觉的。

但如果它们都被声明为 TIntArray,编译器就会接受。

我不知道这是否是正确的术语,但就编译器而言,“myvar :”和“myvar :”之间存在差异。在这种情况下,将是“TIntArray”,并且将是“整数数组”。

var
  myvar1 : array of integer;
  myvar2 : TIntArray;
Run Code Online (Sandbox Code Playgroud)

这两者在所有情况下都不类型兼容。此外,

procedure myproc( AVar : array of integer )
Run Code Online (Sandbox Code Playgroud)

不会接受 myproc(myvar2),因为 myvar2 不是“整数数组”类型。真的吗!它的类型为 TIntArray。看到不同?

现在用任何类型的“记录...结束”,甚至是“记录数组...结束”来替换该声明,您就会开始看到您所要求的局限性。是的,编译器可以很好地消化它。它只是不允许您将任何内容作为与该类型匹配的参数传递!不管你信不信,即使它们“看起来”一模一样。

因此,为了回答您自己的问题,我要求您构建一个重要的示例,其中您提出的内容实际上有意义并且编译器接受它们。因为虽然编译器可能接受您上面创建的孤立示例,但它们在实践中不太可能很好地工作(如果有的话)。

但如果你提出了一个富有洞察力的问题,你就会得到“Audacity”的“A”!