为什么形式[...]的文字具有看似依赖于背景的含义?

时间:2015-06-29 14:30:51

标签: delphi delphi-xe8

考虑以下计划:

{$APPTYPE CONSOLE}

type
  TMyEnum = (enum1, enum2, enum3);

var
  Arr: TArray<TMyEnum>;
  Enum: TMyEnum;

begin
  Arr := [enum3, enum1]; // <-- this is an array
  for Enum in Arr do
    Writeln(ord(Enum));
  Writeln('---');

  for Enum in [enum3, enum1] do // <-- this looks very much like the array above
    Writeln(ord(Enum));
  Writeln('---');

  Readln;
end.

输出结果为:

2
0
---
0
2
---

为什么两个循环产生不同的输出?

3 个答案:

答案 0 :(得分:3)

for Enum in Arr do
  Writeln(ord(Enum));

这里,Arr是一个数组,因此数组的项目按顺序输出。 documentation说:

  

数组以递增顺序遍历。

因此在2之前输出0

for Enum in [enum3, enum1] do
  Writeln(ord(Enum));

这里,[enum3, enum1]是一个集合,并且集合的枚举器恰好按照递增的序数值进行枚举。所以输出首先是0

我不认为在文档中的任何地方陈述了按照该顺序枚举的集合,但根据经验,似乎就是这种情况。但是,由于集合是无序类型,因此无论如何都不应该依赖于它们的枚举顺序。

因此,问题就变成了解[...]如何成为代码中不同点的集合或数组。这一切都源于新的XE7动态数组语法,它引入了(另一种)语法模糊性。我们写的时候

Arr := [enum3, enum1];

然后[enum3, enum1]是一个数组。编译器知道Arr是一个数组,该信息定义了文字的类型。

但是当我们写

for Enum in [enum3, enum1] do

然后[enum3, enum1]是一个集合。这里的文字原则上可以是数组或集合。在这种情况下,我相信编译器总是更喜欢集合。

同样,我找不到任何说明情况的文件,但从经验上来说就是这种情况。大概是因为设置枚举器在新的动态数组语法之前预定了它们,所以当存在歧义时它们优先。

[...]形式的文字的含义取决于其背景。

答案 1 :(得分:3)

因为数组包含订单信息而设备没有。

使用文档说明:

静态或动态数组的internal data format

  

存储为数组的组件类型的连续元素序列。索引最低的组件存储在最低的内存地址中。

使用for in循环is done in incremental order遍历这些索引:

  

数组以递增的顺序遍历,从最低的数组边界开始,以数组大小减去1结束。

另一方面,设置internal data format

  

是一个位数组,其中每个位指示元素是否在集合中。

因此所有这些&#34;指示位&#34;存储在同一个&#34;值&#34;中。这就是为什么一个集可以是typecasted to an Integer type,以及为什么添加这些位的顺序丢失的原因:[enum3, enum1] = [enum1, enum3]

答案 2 :(得分:1)

虽然并不总是理想,但编译器正在使用上下文来确定右侧的类型。你可以看一下字符串作为一个很好的例子:

If constantExpression is a character string, the declared constant is compatible with any string type. If the character string is of length 1, it is also compatible with any character type.

在字符串的情况下,编译器将使用左侧来确定右侧的类型。这与问题中的代码之间的区别在于,这个案例是清楚记录的,而问题中的案例则没有。

使用字符的示例:

{$APPTYPE CONSOLE}

uses
  SysUtils, Classes;

var
  A: Char;
  B: AnsiChar;

begin
  A := 'a';
  B := 'a';

  Writeln(A);
  Writeln(B);

  Readln;
end.

从两者生成的汇编程序表明在两种情况下右侧的处理方式不同:

Project10.dpr.17: A := 'a';
004D6731 66C705C8034E006100 mov word ptr [$004e03c8],$0061
Project10.dpr.18: B := 'a';
004D673A C605CA034E0061   mov byte ptr [$004e03ca],$61

编译器正在使用赋值的目标类型来确定字符串(在本例中为&#39; a&#39;)应该是什么类型。这个问题也发生了类似的事情。

感谢David提供的评论中的其他信息