#c_sharp
Есть у меня перечисления. Очень большой список. Например: enum State : byte { IDLE, //0 - стойка WALK_F, //1 - ходьба вперёд WALK_B, //2 - ходьба назад BLOCK, //3 - блок SIT, //4 - сидение JUMP_UP, //5 - прыжок вверх JUMP_F, //6 - прыжок вперёд JUMP_B, //7 - прыжок назад BLOCK_SIT, //8 - блок в присядке TURN, //9 - поворот RUN, //10 - бег. ... и т.д. }; Можно ли как-то применять эти значения в виде, представленным ниже? byte test = State.RUN; Или мне постоянно придется писать приведение к типу? Типа: byte test = (byte)State.RUN; Вроде бы если enum является перечислением из одного типа, то можно написать enum ENUM_NAME : TYPE { ... }; и должно все работать. Но IDE упорно говорит что все равно надо кастовать. Может я что-то не понимаю. Просто делать такое приведение типа абсолютно везде чересчур затратно. особенно если я решу тип сменить. Таких мест будет сотня. Тем более, если я заранее говорю, что у меня в перечислении будет всё одного конкретного типа, то почему бы такому не работать?
Ответы
Ответ 1
Язык вам тонко намекает, что кастовать туда-сюда между enum и целым типом — не самая здравая и строго типизированная мысль. Вам не должно хотеться повсеместно использовать тип byte, если у вас есть enum с базовым типом byte. Просто используйте сам enum везде, где можно. Где нельзя — преобразуйте тип. И этой операции положено быть явной, потому что вы меняете тип переменной. При этом какой у перечисления базовый тип — значения не имеет. Хоть enum Foo : int преобразовывать к int, хоть enum Bar : byte преобразовывать в byte — операция должна быть явной.Ответ 2
Поскольку в комментариях вы поинтересовались про использование перечисления в качестве индекса массива, отвечу. Допустим, у нас есть перечисление TEnum, основанное на типе int (для простоты) Тогда можно сделать вот так: struct TEnumDict{ private readonly T[] values; TEnumDict() { values = new T[...]; } public T this[TEnum index] { get { return values[(int)index]; } set { values[(int)index] = value; } } } Такую структуру можно использовать вместо массива, и она прекрасно индексируется перечислением. Использование такой структуры практически не несет накладных расходов, поскольку все операции над ней очень простые и JIT их заинлайнит. Если же подобных перечислений становится много - то можно добавить уровень обобщения, ценой некоторого замедления... struct IntValuedEnumDict { private static readonly Func valueof; static IntValuedEnumDict() { var e = Expression.Parameter (); valueof = Expression.Lambda >(Expression.Convert(e, typeof(int)), p).Compile(); } private readonly T[] values; IntValuedEnumDict() { values = new T[...]; } // Число элементов надо тоже определить в статическом конструкторе - но мне лень public T this[TEnum index] { get { return values[valueof(index)]; } set { values[valueof(index)] = value; } } } На самом деле, я не уверен, что такая конструкция будет работать быстро. Надо проверять. Или можно не городить велосипеды, а воспользоваться классом Dictionary. Это не массив, а словарь, и работает он несколько медленнее - зато он готовый и универсальный. Но задумайтесь вот над чем. Зачем вам вообще такие перечисления или константы? Учитесь мыслить объектно-ориентированно! Возможная атака - это тоже объект. Почему бы не сделать вот так: class Attack { public int timesPressed; public int atkTimer; public bool atk; } Такой объект можно привязать напрямую к кнопке, избавившись тем самым не только от константы ATTACK_TYPE_PUNCH - но и от строкового литерала "Punch"! Нужно выполнить действие над этими полями? Нет проблем: class Attack { public int timesPressed; public int atkTimer; public bool atk; public void ButtonPressed() { timesPressed = 0; atkTimer = 0; atk = true; } } Для разных типов атак нужен разный код? Нет проблем: abstract class Attack { public abstract void ButtonPressed(); public abstract int AtkTimer { get; } } class PunchAttack : Attack { public int timesPressed; public int atkTimer; public bool atk; public override void ButtonPressed() { timesPressed = 0; atkTimer = 0; atk = true; } public override int AtkTimer { get { return atkTimer; } } }
Комментариев нет:
Отправить комментарий