8

What List type I should use to store enum values? I have tried with TObjectList, I cast to TObject to Add the value, but can't cast it back to enum when reading from the list.

What list do you use to store enums?

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
elector
  • 1,327
  • 4
  • 26
  • 43

3 Answers3

6

Casting enums to Pointer or TObject and back works just fine. If your Delphi version supports generics use Tim's suggestion, it's better. Alternatively you can use an dynamic array (array of TTestEnum) or create a wrapper class around the dynamic array - that's how generic lists are implemented in Delphi versions capable of generics.

Here's a quick console demo, using TList, not TObjectList because TList makes fewer assumptions about the items it holds.

program Project1;

{$APPTYPE CONSOLE}

uses SysUtils, Classes;

type TTestEnum = (enum1, enum2, enum3, enum4);

var L: TList;
    i: Integer;
    E: TTestEnum;

begin
  L := TList.Create;
  try
    L.Add(Pointer(enum1));
    L.Add(Pointer(enum2));
    L.Add(Pointer(enum3));
    L.Add(Pointer(enum4));
    for i:=0 to L.Count-1 do
    begin
      E := TTestEnum(L[i]);
      case E of
        enum1: WriteLn('enum1');
        enum2: WriteLn('enum2');
        enum3: WriteLn('enum3');
        enum4: WriteLn('enum4');
      end;
    end;
  finally L.Free;
  end;
  ReadLn;
end.
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Cosmin Prund
  • 25,498
  • 2
  • 60
  • 104
  • A sanity check to verify that the value is of the enum type would be a plus - as the list is not typesafe, any enum pointer could be added but since there is no type info in an Pointer, the original type can not be determined when reading the values back. – mjn May 05 '11 at 13:50
  • This also works where the emunerations are of different types, but loses the type information. If you went List.Add(FormState); List.Add(ModalResult); that would work but good luck getting them back out in any meaningful way. –  May 06 '11 at 03:54
  • @moz, @mjn: when you work with such basic collections, you obviously don't get any type safety. That's why I recommend a generic collection if available, or a dynamic array, or a class wrapping a dynamic array. I only wanted to prove casting an enum to a pointer and back is perfectly possible, I'm not saying this is the best way to do it. – Cosmin Prund May 06 '11 at 07:38
  • definitely. I just thought it was worth pointing out that it's not just the detailed type you lose. –  May 07 '11 at 04:45
5

Could you not just use Generics for this?

TList<TEnumName>;
Ken White
  • 123,280
  • 14
  • 225
  • 444
Tim Ebenezer
  • 2,714
  • 17
  • 23
  • 3
    Not in Delphi 2007 (as mentioned in the tags). – Ken White May 05 '11 at 11:05
  • Undid incorrect downvote. I missed the fact that the question when Tim answered it may not have contained the Delphi version, as it was added via an edit at about the time Tim made his post. – Ken White May 05 '11 at 11:21
1

This answer may help. It's about storing records in a TList by creating a descendant to avoid all the typecasting. Note that you won't need to worry about allocating/freeing memory for the enum values, as they're simple ordinal types that fit in the space of a pointer.

Note that you have to typecast to Pointer when Adding to the list, and may have to typecast as `YourEnum(Integer(List[Index])) when reading back. However, the code I linked to shows how to handle both in the descendant class so it's only done once each way, and that's buried in the class implementation.

Community
  • 1
  • 1
Ken White
  • 123,280
  • 14
  • 225
  • 444