考虑以下计划:
{$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 ---
为什么两个循环产生不同的输出?
答案 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)
虽然并不总是理想,但编译器正在使用上下文来确定右侧的类型。你可以看一下字符串作为一个很好的例子:
在字符串的情况下,编译器将使用左侧来确定右侧的类型。这与问题中的代码之间的区别在于,这个案例是清楚记录的,而问题中的案例则没有。
使用字符的示例:
{$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提供的评论中的其他信息