5

次のプログラムを検討してください。

{$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
---

2 つのループが異なる出力を生成するのはなぜですか?

4

3 に答える 3

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

ここでArrは配列なので、配列の項目が順番に出力されます。ドキュメントには次のように記載されています。

配列は昇順でトラバースされます。

したがって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]セットです。ここで、リテラルは原則として配列またはセットのいずれかです。そのような状況では、コンパイラは常にセットを優先すると思います。

繰り返しますが、これがそうであると述べているドキュメントは見つかりませんが、経験的にはそうです。おそらく、セット列挙子は新しい動的配列構文よりも前のものであるため、あいまいさがある場合に優先されます。

フォームのリテラルの意味は、[...]そのコンテキストによって異なります。

于 2015-06-29T14:34:11.977 に答える
1

必ずしも理想的ではありませんが、コンパイラはコンテキストを使用して右辺の型を決定しています。この良い例として、文字列を見ることができます。

constantExpression が文字列の場合、宣言された定数は任意の文字列型と互換性があります。また、文字列の長さが1であれば、どの文字種にも対応しています。

文字列の場合、コンパイラは左側を使用して右側の型を決定します。これと質問のコードの違いは、このケースは明確に文書化されているのに対し、質問のケースは文書化されていないことです。

文字を使用した例:

{$APPTYPE CONSOLE}

uses
  SysUtils, Classes;

var
  A: Char;
  B: AnsiChar;

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

  Writeln(A);
  Writeln(B);

  Readln;
end.

2 つから生成されたアセンブラーは、右側が 2 つのケースで異なる方法で処理されていることを示しています。

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

コンパイラは、代入先の型を使用して、文字列 (この場合は 'a') の型を決定します。質問でも同様のことが起こっています。

コメントで追加情報を提供してくれた David に感謝します

于 2015-06-29T18:12:06.110 に答える