Pass a mixture of differend enums types in delphi

冷暖自知 提交于 2020-01-03 13:37:11

问题


I need to write a procedure where can pass different enum selections.

type
  TEnumOne = (eOneFlagOne, eOneFlagTwo);
  TEnumTwo = (eTwoFlagOne, eTwoFlagTwo);

The method should take different enums:

Process([eOneFlagOne, eTwoFlagTwo]);

I'm trying to implement it like this:

// does not work!
procedure Process(const Enums: array of Variant);
var aValue; Variant
begin
  for aValue in Enums do
  begin
    // of course, can't work...
    if aValue is TEnumOne then
  end; 
end;

So, is there a type instead of Variant, I can choose? Or is the a different approach, I dont' see?


回答1:


Meet the beauty of pascal.

Here's a working example of what you're probably trying to do:

program Project34; {$APPTYPE CONSOLE}

type
  TEnum=(eOneFlagOne,eOneFlagTwo,eTwoFlagOne,eTwoFlagTwo);
  TEnumSet=set of TEnum;

const
  cEnumOne=[eOneFlagOne,eOneFlagTwo];
  cEnumTwo=[eTwoFlagOne,eTwoFlagTwo];

procedure Process(const Enums: TEnumSEt);
var e:TEnum;
begin
  for e in Enums do
    WriteLn(ord(e));
end;

begin
  Process([eOneFlagOne, eTwoFlagTwo]);
  Process(cEnumOne);
  Process(cEnumTwo);
end.

Note that you can also declare the constants like this. Maybe that's clearer:

const
  cEnumOne:TEnumSet=[eOneFlagOne,eOneFlagTwo];
  cEnumTwo:TEnumSet=[eTwoFlagOne,eTwoFlagTwo];



回答2:


To be blunt, when you start trying to bend your language like this, it usually means that your approach is probably wrong. (not always, but usually) I'd be interested to hear what problem you are trying to solve, as maybe there is a better design option.

With what little we know about your problem, I would suggest that either you create 2 functions with the different signatures.
Or
if the required logic branch is similar enough to each other, then you could create a Generic method (assuming Delphi 2009 or higher) using the enum type as your generic parm.

...
procedure Process<T>(const enumParam : T) // Add a generic constraint here as well
begin
...
end;

Seems likely to me however, that the 2 different methods would be the likely best option (or something else entirely)




回答3:


RRUZ deleted his answer, here is a reworked version with type safety. RTTI is used to identify the different enum constants.

function EnumToString(const TypeInfo : pTypeInfo; Ix : Integer) : string;
begin
  Result := GetEnumName(TypeInfo, ix); 
end;

procedure Process( const Args : array of string);
var
  LIndex,ix : integer;
  EnumOne : TEnumOne;
  EnumTwo : TEnumTwo;
begin
  for LIndex := 0 to High(Args) do begin
    ix := GetEnumValue( TypeInfo(TEnumOne), Args[LIndex]);
    if (ix <> -1) then
    begin
      EnumOne := TEnumOne( ix); 
      // do something with EnumOne
      ...
      continue;
    end;

    ix := GetEnumValue( TypeInfo(TEnumTwo), Args[LIndex]);
    if (ix <> -1) then
    begin
      EnumTwo := TEnumTwo( ix); 
      // do something with EnumTwo
      ...
      continue;
    end; 
    ... 
    etc

  end;        
end;

Process( [EnumToString(TypeInfo(TEnumOne),Ord(TEnumOne.eOneFlagOne)),
          EnumToString(TypeInfo(TEnumTwo),Ord(TEnumTwo.eTwoFlagTwo))]);



回答4:


An alternative is to keep it as just one enum:

TEnum = (eOneFlagOne, eOneFlagTwo, eTwoFlagOne, eTwoFlagTwo);

The Process function would then look like this:

procedure Process(Enums: Array of TEnum);
var 
  aValue: TEnum;
begin
  for aValue in Enums do
  begin
    if aValue in [eOneFlagOne, eOneFlagTwo] then
      // Handle the eOne enums
    else if aValue in [eTwoFlagOne, eTwoFlagTwo] then
      // Handle the eTwo enums
  end; 
end;


来源:https://stackoverflow.com/questions/11110704/pass-a-mixture-of-differend-enums-types-in-delphi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!