Обращение к элементам перечисления по их номерам

Перечисления играют далеко не последнюю роль в языке программирования Delphi.

В этой статье речь пойдёт об одной тонкости в работе с перечислениями, которую, к сожалению, в большинстве случаев обходят стороной. Это возможность обращения к элементам перечисления по их порядковым номерам.

Опишем перечисление:

Для начала, рассмотрим пример «классического» варианта обращения к элементам перечисления в виде простейшего кода с использованием оператора case:

Как обратиться к элементам перечисления по порядковому номеру? На самом деле очень просто. Для наглядности достаточно слегка изменить вышеприведённый пример.

Результат работы кода, который приведён и в этом и в предыдущем примере, будет одинаковым.

Использование имени типа вместо имени переменной в качестве значения константы выбора обусловлено семантикой перечислений и оператора case. Поэтому, в случае указания имени переменной в место имени типа, компилятор при построении программы выдаст ошибку.

Зачем же нужно обращаться к элементу перечисления по порядковому номеру?

Причин здесь может быть много. Начиная от банального упрощения (вместо «чрезмерно длинного» имени элемента написать «сокращённый вариант», хотя упрощение в данном случае довольно сомнительно (в комментариях меня поправили)) до решения достаточно сложных задач, в том числе по обфускации на уровне исходного кода.

В любом случае, к данной возможности, в прочем как и к любой другой, имеет смысл прибегать только там, где её использование действительно оправдано.

2 комментария

  1. Странно все это.

    Причин здесь может быть много. Начиная от банального упрощения (вместо «чрезмерно длинного» имени элемента написать «сокращённый вариант») до решения достаточно сложных задач, в том числе по обфускации на уровне исходного кода.

    enum введен как раз для того, чтобы вместо непонятных цифр (т.н. «магических чисел») писать имена, которые хоть о чем-то скажут.
    Ну и менять безболезнено тоже. Типа был у вас енам для состояний игры

    И решили вы в какой то момент убрать состояние Ready.
    Если вы во всем коде писали так:

    то проблем не будет.
    Но а если писали

    то готовьтесь во всем коде менять цифры 2 на 1, 3 — на 2, и т.п.
    Притом надо ведь учесть, что не везде 2 — это Load, т.е. если где-то вы проверяли четность числа

    то тут не надо менять на

    короче проблем хлебнуть можно слихвой.
    В любом языке программирования где есть именованные константы типа енамов, их надо использовать, иначе код запутывается. Запутанный код — это плохо.
    Обфускация на уровне исходного кода…, а зачем?
    Не хочешь чтобы твой код кто-то читал — не делай его опенсорсным.
    Если кому то очень надо, они расколупают дизассемблированный код, а там замена енамов цифрами никак не сыграет.
    Короче в жизненном цикле любой программы есть стадия поддержки. Если говнокодить, то код не прочитается, но и поддерживать самому будет очень сложно.
    Если уже очень, очень надо публиковать исходный код, но нельзя чтоб его прочитали, вроде бы можно воспользоваться обфускаторами. Вроде бы они есть и могут заменить тебе имена как-нибудь непредсказуемо.
    В любом случае, в рабочем проекте говнокодить не стоит ИМХО.

    1. К сожалению Вы, видимо, просто не до конца поняли смысл представленного кода.

      Но а если писали

      В Вашем коде state приводится к int. В моей статье этого приведения нет.
      Пожалуйста, обратите внимание, что используется не 0, 1 и т.д., а enum(0), enum(1) и т.д..
      Для того, чтобы привести enum к integer, то есть полностью перейти к «магическим числам» необходимо использовать функцию ord. Тогда оператор case выглядел бы вот так:

      Это особенность языка Delphi. Предполагаю, что Вас просто ввела в заблуждение семантика языка C++.
      Конечно, в случае удаления элемента из перечисления, данный приём создаёт опасность ошибки. Однако, «мёртвые» логические ветви это, по ряду причин, тоже не есть хорошо.
      Поэтому, в данном случае, код, где это перечисление используется, править всё равно придётся. Вопрос только в том, когда это придётся делать. Сразу или спустя некоторое время?..

      В любом языке программирования где есть именованные константы типа енамов, их надо использовать, иначе код запутывается. Запутанный код — это плохо.

      С точки зрения процесса разработки и сопровождения Вы по большей части правы. Принцип KISS (англ. keep it short and simple — «делай короче и проще») здесь один из основополагающих. Но, даже он не панацея и не всегда приемлем. Очень многие, даже столь фундаментальные, вещи имеют исключения.
      Особенно когда необходимо сознательно запутать код.

      Обфускация на уровне исходного кода…, а зачем?
      Не хочешь чтобы твой код кто-то читал — не делай его опенсорсным.
      Если кому то очень надо, они расколупают дизассемблированный код, а там замена енамов цифрами никак не сыграет.

      Те, кому очень надо, преодолеют и не такую защиту. Простите, но таким образом из Вашей логики следует, что программы не стоит вообще защищать?
      Речь не идёт о 100% защите. 100% защита это утопия. Цель защиты — максимально затруднить несанкционированное использование программы как продукта и как результатов интеллектуального труда. Не более того.
      Кстати, для дизассемблирования тоже есть средства противодействия.

      Если уже очень, очень надо публиковать исходный код, но нельзя чтоб его прочитали, вроде бы можно воспользоваться обфускаторами. Вроде бы они есть и могут заменить тебе имена как-нибудь непредсказуемо.

      Для Open Source данный вопрос не актуален. Данные проекты специально делают открытыми.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *