Ответ 1
Простой:
type
TWeekdays = (wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday);
procedure Test;
var
el: TWeekdays;
begin
for el := Low(TWeekdays) to High(TWeekdays) do
; //
end;
Я хочу перебирать элементы в перечислении.
Я хотел бы сказать что-то вроде этого:
type
TWeekdays = (wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday);
...
elementCount := GetElementCount(TypeInfo(TWeekDays));
for i := 0 to elementCount - 1 do begin
ShowMessage(GetEnumName(TypeInfo(TWeekdays),i));
end;
Ближайшим, с которым я смог приехать, является следующее:
function MaxEnum(EnumInfo: PTypeInfo): integer;
const
c_MaxInt = 9999999;
var
i: integer;
s: string;
begin
//get # of enum elements by looping thru the names
//until we get to the end.
for i := 0 to c_MaxInt do begin
s := Trim(GetEnumName(EnumInfo,i));
if 0 = Length(s) then begin
Result := i-1;
Break;
end;
end;
end;
Что я использую так:
procedure TForm1.BitBtn1Click(Sender: TObject);
var
i, nMax: integer;
begin
ListBox1.Clear;
nMax := MaxEnum(TypeInfo(TWeekdays));
for i := 0 to nMax do begin
ListBox1.Items.Add(GetEnumName(TypeInfo(TWeekdays),i));
end;
end;
Это хорошо работает, за исключением того, что список выглядит так (обратите внимание на два последних элемента):
wdMonday
wdTuesday
wdWednesday
wdThursday
wdFriday
Unit1
'@'#0'ôÑE'#0#0#0#0#0#0#0#0#0#0#0#0#0 <more garbage characters>
Два элемента в конце, очевидно, не то, что я хочу.
Есть ли лучший способ итерации по элементам перечисляемого типа?
Если нет, то можно ли считать, что всегда будет два дополнительных элементов, используя мой текущий метод? Очевидно, что это имя группы... но что такое символ "@"? Это действительно мусор, или это больше информации о типе?
Я использую Delphi 2007. Спасибо за любые идеи.
Простой:
type
TWeekdays = (wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday);
procedure Test;
var
el: TWeekdays;
begin
for el := Low(TWeekdays) to High(TWeekdays) do
; //
end;
Это сложнее, чем при использовании специальных перечислений... давайте посмотрим действительно 100% -ное рабочее решение для сложного перечисленного определения:
type
TmyEnumType=(myEnumTypeA=5,myEnumTypeB=2,myEnumTypeC=9);
const
myEnumTypeOrder:Array[1..3] of TmyEnumType=(myEnumTypeA,myEnumTypeB,myEnumTypeC);
procedure TForm1.Button1Click(Sender: TObject);
var
myEnumTypeVariable:TmyEnumType;
begin
myEnumTypeVariable:=Low(TmyEnumType);
for myEnumTypeVariable in myEnumTypeOrder
do begin
ShowMessage(IntToStr(Ord(myEnumTypeVariable))); // Sample code to show enum integer value
// Extra code you neede
end;
end;
// This code shows three messages in this secuence: 5, 2, 9
// Correct number of elements and in the correct order
Примечания:
Почему это было сделано так?:
TmyEnumType
, присваивает ему (9-2 + 1 = 8) элементы (от нижнего (2) до более высокого (9), поэтому допустимые значения для такого типа относятся к порядку 2 к порядку 9Трюк:
Если вы попробуете этот другой (логический человеческий образ мышления), он не будет работать (независимо от того, используете ли он цикл, while цикл, повторяйте до и т.д.):
type
TmyEnumType=(myEnumTypeA=5,myEnumTypeB=2,myEnumTypeC=9);
procedure TForm1.Button1Click(Sender: TObject);
var
myEnumTypeVariable:TmyEnumType;
begin
for myEnumTypeVariable:=Low(TmyEnumType) to High(TmyEnumType);
do begin
ShowMessage(IntToStr(Ord(myEnumTypeVariable))); // Sample code to show enum integer value
// Extra code you neede
end;
end;
// This code shows eight messages in this secuence: 2, 3, 4, 5, 6, 7, 8, 9
// Inorrect number of elements and in order is lost
Это то, что я проверил самостоятельно на Turbo Delphi 2006.
Вы можете использовать Succ (x) и Pred (x) для прокрутки перечисления. Но не забудьте проверить границы, чтобы не попробовать Succ (x) в последнем элементе перечисления!
Пример:
type
TWeekdays = (wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday);
procedure Test;
var
val: TWeekdays;
begin
val := wdTuesday;
val := Succ(val); // wdWednesday
val := wdFriday;
val := Pred(val); // wdThursday,
end;
Я сделал EnumerationEnumerator, чтобы вы могли использовать его в инструкции "for... in" в Delphi. Тем не менее, тогда он иногда генерирует внутренние ошибки компилятора.
Edit:
Чтобы заставить его работать в Delphi 2007 и выше, см. эту статью в блоге (и довольно интересная дискуссия).