问题
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