考虑以下程序:
{$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.
Run Code Online (Sandbox Code Playgroud)
输出是:
2 0 --- 0 2 ---
为什么两个循环产生不同的输出?
for Enum in Arr do
Writeln(ord(Enum));
Run Code Online (Sandbox Code Playgroud)
这里,Arr是一个数组,因此数组中的项按顺序输出。文档说:
以升序遍历数组。
因此2是之前的输出0。
for Enum in [enum3, enum1] do
Writeln(ord(Enum));
Run Code Online (Sandbox Code Playgroud)
这里,[enum3, enum1]是一个集合,并且集合的枚举器恰好按顺序值递增的顺序进行枚举。所以输出是0第一位的。
我认为文档中没有任何地方说明集合是按该顺序枚举的,但从经验来看似乎确实如此。然而,由于集合是一种无序类型,因此无论如何都不应该依赖它们的枚举顺序。
因此,问题就变成了理解[...]代码中不同点如何成为集合或数组。这一切都源于新的 XE7 动态数组语法,它引入了(另一个)语法歧义。当我们写的时候
Arr := [enum3, enum1];
Run Code Online (Sandbox Code Playgroud)
然后[enum3, enum1]是一个数组。编译器知道这Arr是一个数组,并且该信息定义了文字的类型。
但是当我们写
for Enum in [enum3, enum1] do
Run Code Online (Sandbox Code Playgroud)
然后[enum3, enum1]是一个集合。这里的文字原则上可以是数组或集合。在这种情况下,我相信编译器总是更喜欢集合。
同样,我找不到任何文档表明情况如此,但从经验上来看确实如此。据推测,由于集合枚举器早于新的动态数组语法,因此当存在歧义时它们优先。
形式的字面意义[...]取决于其上下文。