При работе с перечислениями в Delphi иногда возникает необходимость их хранения в списках. Вопрос выбора подходящего типа списка для хранения перечислений может быть непростым, особенно если требуется обеспечить типобезопасность и удобство использования. В данной статье мы рассмотрим несколько подходов к решению этой задачи.
Использование TObjectList
Один из подходов — использование TObjectList<T> для хранения перечислений. Однако, как отмечают разработчики, при работе с TObjectList могут возникнуть сложности с приведением типов при добавлении и извлечении элементов из списка.
var
List: TObjectList;
EnumValue: Pointer;
begin
List := TObjectList.Create;
try
EnumValue := Pointer(EnumValue1); // Пример перечисления
List.Add(Object(EnumValue));
// ...
// Извлечение значений из списка
with List[0] do
EnumValue := TEnumType(Integer(dynamic_cast<Pointer>(Self)));
finally
List.Free;
end;
end;
Использование TList с приведением типов
Другой вариант — использовать TList<Pointer> и привести типы при добавлении и извлечении элементов. Этот подход проще и не требует дополнительного управления памятью, так как значения перечислений могут быть представлены в виде указателей.
var
List: TList;
EnumValue: TTestEnum;
begin
List := TList.Create;
try
List.Add(Pointer(EnumValue1));
// ...
for var i := 0 to List.Count - 1 do
begin
EnumValue := TTestEnum(Integer(List[i]));
// Обработка значения перечисления
end;
finally
List.Free;
end;
end;
Использование Generics
С версии Delphi 2007 и выше доступна возможность использования Generics, что позволяет создавать типизированные списки:
type
TEnumList = TList<TTestEnum>;
var
EnumList: TEnumList;
begin
EnumList := TList<TTestEnum>.Create;
try
EnumList.Add(TTestEnum.enum1);
// ...
finally
EnumList.Free;
end;
end;
Использование динамических массивов и обёрток
Для версий Delphi, не поддерживающих Generics, можно использовать динамические массивы или создать обёртки вокруг них. Это позволит обеспечить типобезопасность и упростить работу со списками.
Пример использования TList без TObjectList
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.
Заключение
Выбор типа списка для хранения перечислений зависит от многих факторов, включая версию Delphi, требования к типобезопасности и удобству использования. Приведённые выше примеры показывают, что существует несколько способов решения задачи, и каждый разработчик может выбрать наиболее подходящий для своего проекта.
Альтернативные варианты хранения перечислений в Delphi: использование `TObjectList`, `TList` с приведением типов, Generics, динамические массивы и обёртки.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS