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

时间:2014-11-26 02:18:48

标签: arrays delphi record

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

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

var
  OnesRecord: TMyRecord;

对于数组,它也用作:

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

var
  OnesRecord: array of TMyRecord;

我的问题如下:

为什么不应该使用第一种方法来实现数组:

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

var
  OnesRecord: TMyRecord;

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

,会有什么不同
var
  OnesRecord: record
    data1: sometype;
    data2: sometype;
  end;

var
  OnesRecord: array of record
    data1: sometype;
    data2: sometype;
  end;

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

所以,是这样的:

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

var
  OnesRecord: array of TMyRecord;

与此不同:

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

var
  OnesRecord: array of array of TMyRecord;

4 个答案:

答案 0 :(得分:5)

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

type
  TPoints = array of record
    X, Y: Double;
  end;

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

问题的其他方面在逻辑上是相同的。是数组的数组,包含记录的记录,匿名记录和数组作为变量类型。问题和设计考虑因素是一样的。


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

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

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

type
  TPoint = record
    X, Y: Double;
  end;
  TPoints = array of TPoint;

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

答案 1 :(得分:4)

使用Type声明可以让您轻松地在多个其他类型或变量中使用它,并将该类型的变量或常量传递给过程和函数。

Type 
  TCatRecord = Record
    Name  : string;
    Color : string;
  End;
  TCatArray = Array of TCatRecord;
Var
  MyCat : TCatRecord;
  NeighbourhoodCats : TCatArray;
...
Procedure SpayACat(aCat: TCatRecord);
Function PickCutestCat(SomeCats: TCatArray): TCatRecord;
...
MyCat := PickCutestCat(NeighbourhoodCats); 

答案 2 :(得分:4)

做你正在做的事情没什么不对,就像没有什么能阻止你重载Add()运算符来做乘法。

你的问题完全是理论上的,因此很难用这种或那种方式说出来。是的,这些结构是“合法的”。所以呢?

这就像是在你发现自己可以走在你的手上之后询问走路而不是走路。

所有情况下的问题都是一样的......你为什么要这样做?

与其询问“合法”但没有人使用的编码方法,为什么不尝试展示这样的用途会被证明是有利的例子呢?

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

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

您通常将数组声明为“数组”而不是“数组记录...结束”。

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

你显然没有太多的经验,因为你不能在非常狭窄的环境中使用这些结构。

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

type
 TIntArray = array of integer;

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

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

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

var
  myvar1 : array of integer;
  myvar2 : TIntArray;

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

procedure myproc( AVar : array of integer )

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

现在用任何类型的“记录......结束”替换该声明,甚至是你的“记录......结束”的东西,你开始看到你所要求的限制。是的,编译器消化它就好了。它只是不允许你作为匹配该类型的参数传递任何东西!即使他们“看起来”完全一样,不管你信不信。

所以,为了回答你自己的问题,我挑战你构建一个非平凡的例子,你提出的事情实际上是有意义的,编译器接受它们。因为虽然编译器可能接受您在上面创建的孤立示例,但它们在实践中不太可能工作得很好(如果有的话)。

但是,当你提出一个富有洞察力的问题时,你会得到Audacity的'A'!

答案 3 :(得分:1)

为了补充选择的答案,我们在这里为单位的全球变量提供了一个没有很好记录的功能:

声明具有初始值的记录变量数组

type
  TPatch = Packed Record
    Pos: NativeUInt;
    Old: Byte;
    Sup: Byte;
  End;

var
  OpCodes: Array [1..5] of TPatch = (
    (Pos: $044773CF; Old: $7D; Sup: $EB),
    (Pos: $04477400; Old: $0D; Sup: $0B),
    (Pos: $0447D370; Old: $E3; Sup: $E9),
    (Pos: $0447D371; Old: $01; Sup: $99),
    (Pos: $0447D372; Old: $13; Sup: $00),
  );

现在你可以使用