powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Enum to string и обратно
25 сообщений из 42, страница 1 из 2
Enum to string и обратно
    #40040953
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А как бы проще организовать конвертацию энумератора в строку и обратно для таких конечных строк
'lower', 'upper', 'title', 'none', 'assume-lower', 'assume-title', 'assume-upper'?

Функции GetEnumName/GetEnumValue не подходят, т.к. конечные строки содержат знак "-" и я не объявлю такие идентификаторы

Таких энумераторов много, так что не очень хочется под каждый писать отдельные функции конвертации

С уважением, Vasilisk
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40040955
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Напиши свою функцию. Ну или класс, если
требуется что-то большее, чем просто имена.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40040956
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

System.TypInfo.AddEnumElementAliases
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40040957
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
> System.TypInfo.AddEnumElementAliases

Ух-ты, круто...
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40040971
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey
System.TypInfo.AddEnumElementAliases
GetEnumValue заработало. GetEnumName возвращает оригинальное имя
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40040979
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Альтенативный вопрос
Код: pascal
1.
TTestEnum = ([CustomName('b')] a)


Можно ли получить TRttiType для элемента перечисления, чтобы потом у него вызвать GetAttributse()?
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40040988
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Родилaсь такая структура
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
type
  TEnumAliasesManager<T> = record
  strict private
    type
      TEnumValue = record
      case TOrdType of
        otSByte: (SByte: ShortInt);
        otUByte: (UByte: Byte);
        otSWord: (SWord: SmallInt);
        otUWord: (UWord: Word);
        otSLong: (SLong: Integer);
        otULong: (ULong: Cardinal);
      end;
      PEnumValue = ^TEnumValue;
  strict private
    class var
      FAliases: TArray<string>;
  strict private
    class procedure CheckRegistered; static;
    class procedure SizeError; static; inline;
    class function IndexOf(const AStr: string): Integer; static;
  public
    class procedure Register(const AAliases: array of string); static;
    class function EnumToString(const AVal: T): string; static;
    class function StringToEnum(const AVal: string): T; static;
  end;

  EEnumAliasesManagerError = class(Exception);

class procedure TEnumAliasesManager<T>.CheckRegistered;
begin
  if FAliases = nil then
    raise EEnumAliasesManagerError.Create('No aliases registered');
end;

class procedure TEnumAliasesManager<T>.SizeError;
begin
  raise EEnumAliasesManagerError.Create('Unknown enumeration size');
end;

class function TEnumAliasesManager<T>.IndexOf(const AStr: string): Integer;
begin
  for Result := 0 to Length(FAliases) - 1 do begin
    if AStr = FAliases[Result] then
      Exit;
  end;
  raise EEnumAliasesManagerError.CreateFmt('Alias "%s" not found', [AStr]);
end;

class procedure TEnumAliasesManager<T>.Register(
  const AAliases: array of string);
var
  LTypeInfo: PTypeInfo;
  LMinValue: Integer;
  LMaxValue: Integer;
  LLen: Integer;
begin
  LTypeInfo := TypeInfo(T);
  if LTypeInfo^.Kind <> tkEnumeration then
    raise EEnumAliasesManagerError.Create('Type must be Enumeration');
  if LTypeInfo^.Kind <> tkEnumeration then
    raise Exception.Create('Type must be Enumeration');
  LMinValue := LTypeInfo^.TypeData^.MinValue;
  if LMinValue < 0 then begin  // WordBool, LongBool etc
    LMinValue := 0;
    LMaxValue := 1
  end else
    LMaxValue := LTypeInfo^.TypeData^.MaxValue;

  LLen := Length(AAliases);
  if LMaxValue - LMinValue + 1 <> LLen then
    raise Exception.Create('Invalid aliases size');

  SetLength(FAliases, LLen);
  TArray.Copy<string>(AAliases, FAliases, LLen);
end;

class function TEnumAliasesManager<T>.EnumToString(const AVal: T): string;
var
  LTypeInfo: PTypeInfo;
  LEnumVal: PEnumValue;
begin
  CheckRegistered;
  LTypeInfo := TypeInfo(T);
  LEnumVal := @AVal;
  case LTypeInfo^.TypeData^.OrdType of
    otSByte: Result := FAliases[LEnumVal^.SByte];
    otUByte: Result := FAliases[LEnumVal^.UByte];
    otSWord: Result := FAliases[LEnumVal^.SWord];
    otUWord: Result := FAliases[LEnumVal^.UWord];
    otSLong: Result := FAliases[LEnumVal^.SLong];
    otULong: Result := FAliases[LEnumVal^.ULong];
  else
    SizeError;
  end;
end;

class function TEnumAliasesManager<T>.StringToEnum(const AVal: string): T;
var
  LTypeInfo: PTypeInfo;
  LEnumVal: PEnumValue;
  LIdx: Integer;
begin
  CheckRegistered;
  LIdx := IndexOf(AVal);
  LTypeInfo := TypeInfo(T);
  LEnumVal := @Result;
  case LTypeInfo^.TypeData^.OrdType of
    otSByte: LEnumVal^.SByte := LIdx;
    otUByte: LEnumVal^.UByte := LIdx;
    otSWord: LEnumVal^.SWord := LIdx;
    otUWord: LEnumVal^.UWord := LIdx;
    otSLong: LEnumVal^.SLong := LIdx;
    otULong: LEnumVal^.ULong := LIdx;
  else
    SizeError;
  end;
end;

и использование
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
type
  TTestEnum1 = (en11, en12);
  TTestEnum2 = (en21, en22, en23);

procedure TForm1.Button1Click(Sender: TObject);
var
  LStr: string;
  LEn1: TTestEnum1;
  LEn2: TTestEnum2;
begin
  TEnumAliasesManager<TTestEnum1>.Register(['a', 'b']);
  TEnumAliasesManager<TTestEnum2>.Register(['x', 'y', 'z']);
  LStr := TEnumAliasesManager<TTestEnum1>.EnumToString(en12);
  LStr := TEnumAliasesManager<TTestEnum2>.EnumToString(en23);
  LEn1 := TEnumAliasesManager<TTestEnum1>.StringToEnum('b');
  LEn2 := TEnumAliasesManager<TTestEnum2>.StringToEnum('z');
end;

...
Рейтинг: 0 / 0
Enum to string и обратно
    #40041054
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey
_Vasilisk_,

System.TypInfo.AddEnumElementAliases


http://docwiki.embarcadero.com/Libraries/Sydney/en/System.TypInfo.AddEnumElementAliases

а справки и примеров нет :(
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40041097
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Ммм?
Код: pascal
1.
2.
3.
4.
  if LTypeInfo^.Kind <> tkEnumeration then
    raise EEnumAliasesManagerError.Create('Type must be Enumeration');
  if LTypeInfo^.Kind <> tkEnumeration then
    raise Exception.Create('Type must be Enumeration');
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40041099
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,

вдруг просочится?
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40041315
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp
Ммм?
Рука дрогнула. Дважды Ctrl-V нажал :)
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40041371
bk0010
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadman
alekcvp,

вдруг просочится?
И такое бывало (в смысле, приходилось писать по 2 одинаковых проверки подрят). На Lotus Notes, ЕМНИП.
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40041438
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    LTypeInfo := TypeInfo(T);
  if LTypeInfo^.Kind <> tkEnumeration then
    raise EEnumAliasesManagerError.Create('Type must be Enumeration');

  LMinValue := LTypeInfo^.TypeData^.MinValue;
  if LMinValue < 0 then begin  // WordBool, LongBool etc
    LMinValue := 0;
    LMaxValue := 1
  end else
    LMaxValue := LTypeInfo^.TypeData^.MaxValue;


я бы такие проверки в конструктор класса убрал, это и быстрее и проверка будет при запуске, а не при использовании
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40041450
Фотография defecator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
kealon(Ruslan)
_Vasilisk_,

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    LTypeInfo := TypeInfo(T);
  if LTypeInfo^.Kind <> tkEnumeration then
    raise EEnumAliasesManagerError.Create('Type must be Enumeration');

  LMinValue := LTypeInfo^.TypeData^.MinValue;
  if LMinValue < 0 then begin  // WordBool, LongBool etc
    LMinValue := 0;
    LMaxValue := 1
  end else
    LMaxValue := LTypeInfo^.TypeData^.MaxValue;



я бы такие проверки в конструктор класса убрал, это и быстрее и проверка будет при запуске, а не при использовании


а я не люблю в конструкторе никаких исключений поднимать
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40041458
asutp2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А я задачу, аналогичную задаче ТC, сделал через helper, реализовал в нем .ToString для enum и всё работает)
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40041680
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)
я бы такие проверки в конструктор класса убрал, это и быстрее и проверка будет при запуске, а не при использовании
О! Спасибо за идею!
asutp2
А я задачу, аналогичную задаче ТC, сделал через helper, реализовал в нем .ToString для enum и всё работает)
Замечательно! А если энумераторов десяток? Десять хелперов?
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40041704
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)
я бы такие проверки в конструктор класса убрал,
Компилятор напутал с очередностью вызова классовых конструкторов. В итоге классовый конструктор, откуда идет вызов метода
Код: pascal
1.
TEnumAliasesManager<T>.Register

вызывается раньше чем классовый конструктор
Код: pascal
1.
TEnumAliasesManager<T>.Create;

Т.е. проверку нужно вставлять в двух местах: и в конструкторе и в методе
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40041803
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_
kealon(Ruslan)
я бы такие проверки в конструктор класса убрал,
Компилятор напутал с очередностью вызова классовых конструкторов.

есть простое правило: "если программа работает неправильно, значит ты что-то неправильно написал"
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40041828
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)
есть простое правило: "если программа работает неправильно, значит ты что-то неправильно написал"
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
interface

type
  TClass1<T> = class
  strict private
    class constructor Create;
  public
    class procedure Method; static;
  end;

  TClass2 = class
  strict private
    class constructor Create;
  end;

implementation

class constructor TClass1<T>.Create;
begin
  ShowMessage(ClassName + '.Create');
end;

class procedure TClass1<T>.Method; 
begin
  ShowMessage(ClassName + '.Method');
end;

class constructor TClass2.Create;
begin
  ShowMessage(ClassName + '.Create');
  TClass1<Byte>.Method;
end;

Запускаю и вижу
TClass2.Create
TClass1<Byte>.Method
TClass1<Byte>.CreateНу конечно же я что-то неправильно написал
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40041839
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Наверное это потому что ты вызываешь метод класса из конструктора другого класса, нет?..
Никто не обещал что конструктор будет вызываться при любом обращении к классу.

Более того, если прочитать справку то там, внезапно, написано:
Note: Even though the compiler takes care of ordering the initialization of classes, in some complex scenarios, ordering may become random. This happens when the class constructor of a class depends on the state of another class that, in turn, depends on the first class.
У тебя класс2 зависит от класса1, потому что он вызывает его методы, а класс1 зависит от класса2, потому что это дженерик и до первого обращения к нему с указанием типа его вообще не существует.

Более того, дальше тебя ждёт ещё больше сюрпризов, потому что:
Note: The class constructor for a generic class or record may execute multiple times. The exact number of times the class constructor is executed in this case depends on the number of specialized versions of the generic type. For example, the class constructor for a specialized TList<String> class may execute multiple times in the same application.
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40041987
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,

1-е верно, компилятор может упустить вызов конструктора если он например может его выкинуть
или если "не видит" связи между вызовами - запустить его как получится


авторNote: The class constructor for a generic class or record may execute multiple times. The exact number of times the class constructor is executed in this case depends on the number of specialized versions of the generic type. For example, the class constructor for a specialized TList<String> class may execute multiple times in the same application. а вот это неправда, там такой же счётчик как и у Unit-ов. Эту багу хорошо повыправляли

на 10-ке

Код: plaintext
1.
2.
3.
TClass1<System.Byte>.Create
TClass2.Create
TClass1<System.Byte>.Method
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40041996
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)
а вот это неправда, там такой же счётчик как и у Unit-ов. Эту багу хорошо повыправляли

Это цитата из справки, если что. Причём из справки для 10.4.
Так что если ты с чем-то не согласен - пиши сразу в Эмбу 😁
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40042012
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,

и что же я им напишу, верните багу назад в соответствии с этой документацией?
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40042013
asutp2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Столько проблем, хотя в варианте с хелпером все работает предсказуемо и без багов)))
...
Рейтинг: 0 / 0
Enum to string и обратно
    #40042024
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asutp2,

да я кажется знаю где у _Vasilisk_ бага, он как-то просил пример по одному вопросу "почему так делать нельзя", похоже он сам его и написал
но пока не видно как он его использует, однозначно утверждать нельзя
...
Рейтинг: 0 / 0
25 сообщений из 42, страница 1 из 2
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Enum to string и обратно
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]