23

最初のメンバーに通常の0(ゼロ)ではなく1(1)の序数値を持たせたい次の列挙型を宣言しました。

  type
    TMyEnum = (
               meFirstValue = 1,
               meSecondValue,
               meThirdValue
              );

たとえばGetEnumName()の呼び出しの一部として、TypeInfo()を呼び出すと、コンパイラエラーが発生します。

  GetEnumName(TypeInfo(TMyEnum), Ord(aValue));

エラー:「E2134:タイプ'TMyEnum'にはtypeinfoがありません」

どうしてこれなの?

クラスがtypeinfoを持つのは、 $ Mコンパイラオプションを有効にしてコンパイルした場合、または( TPersistentなどのクラスから派生した)場合のみですが、列挙型のtypeinfoを持つための特別な条件はないと思いました。

4

3 に答える 3

37

不連続な列挙、およびゼロから始まらない列挙には、typeinfoがありません。tkEnumerationtypeinfoを実装するには、下位互換性の問題があるため、既存の形式とは異なる形式にする必要があります。

Delphi 2010に(またはおそらくより適切な名前のメンバー)を実装することを検討しましたtkDiscontiguousEnumerationが、それらの相対的な不足と列挙の難しさを考慮すると、メリットは小さいように見えました-範囲を効率的にエンコードするにはどうすればよいですか?一部のエンコーディングは、一部のシナリオには適していますが、他のシナリオには適していません。

于 2009-09-14T10:00:47.383 に答える
23

タイプ情報は、特定の順序値が割り当てられている列挙型ではサポートされていません。その結果、列挙型メンバーは、コンパイラーによって通常割り当てられる順序値とは異なる順序値を持ちます。

特定の値が必須または望ましい場合は、必要に応じて「未使用」の列挙型メンバーを挿入して列挙型を「パディング」する必要があります。例(強調のための追加のインデントのみ):

  type
    TMyEnum = (
                meNOTUSED1,   {= 0}
               meFirstValue,  {= 1} 
               meSecondValue,
               meThirdValue
              );

次に、サブ範囲を使用して、未使用の初期値を「フィルター」で除外できます。

   TValidMyEnum = meFirstValue..meThirdValue;

ただし、プロジェクト全体でサブレンジタイプを使用できるように、元の列挙型の名前を変更することを検討することもできます。

列挙型に「ギャップ」が含まれている場合、サブ範囲は十分ではありません。

  type
    TMyEnum = (
                meNOTUSED1,   {= 0}
               meFirstValue,  {= 1} 
               meSecondValue,
               meThirdValue,
                meNOTUSED2,
               meFinalValue   {= 5}
              );

この場合、コンパイル時の範囲チェックを拡張して未使用のメンバーを除外する簡単な方法はありませんが、いくつかのセットタイプを使用すると、必要なランタイムチェックを実装するビジネスが簡素化されます。

  type
    TMyEnums = set of TMyEnum;

  const
    meNOTUSED      = [meUNUSED1, meUNUSED2]; //  .. etc as required
    meValidValues  = [Low(TMyEnum)..High(TMyEnum)] - meNOTUSED;


  if NOT (aValue in meValidValues) then
     // etc
于 2009-09-14T09:42:12.117 に答える
0

列挙型を特定の値に(およびその逆に)変換する場合は、通常、列挙型の値ごとに必要な値を使用して配列constを作成します。

Const MyEnumValues: array[TMyEnum] of integer = (1,2,5);

このように列挙型が展開されると、配列値が欠落していることを示すコンパイラエラーが発生します。

列挙型の順序を変更する場合は、それに応じて値を変更する必要があることに注意してください。

列挙値の「値」を取得するには、次のように記述します。

Value := MyEnumValues[myenum];

そして、'value'に基づいて列挙値を取得するには、MyEnumValuesの値をループします。

Function GetEnumByValue(value:integer): TMyEnum;
Var
  myenum: TMyEnum;
Begin
  For myenum = low(TMyEnum) to high(TMyEnum) do
    If MyEnumValues[myenum] = value then
      exit(myenum);
  Raise exception.create(‘invalid value for tmyenum’);
End;
于 2019-09-17T19:24:03.480 に答える