Как конфертировать из System.Enum в base integer?

Я хотел бы создать общий метод преобразования любого производного типа System.Enum в соответствующее целочисленное значение без литья и, желательно, без синтаксического анализа строки.

Например, я хочу что-то вроде этого:

// Trivial example, not actually what I'm doing.
class Converter
{
    int ToInteger(System.Enum anEnum)
    {
        (int)anEnum;
    }
}

Но это не работает. Resharper сообщает, что вы не можете использовать выражение типа "System.Enum" для ввода "int".

Теперь я придумал это решение, но я предпочел бы иметь что-то более эффективное.

class Converter
{
    int ToInteger(System.Enum anEnum)
    {
        return int.Parse(anEnum.ToString("d"));
    }
}

Любые предложения?

Ответ 1

Если вы не хотите использовать,

Convert.ToInt32()

мог сделать трюк.

Прямая трансляция (через (int)enumValue) невозможна. Обратите внимание, что это также будет "опасно", поскольку перечисление может иметь разные базовые типы (int, long, byte...).

Более формально: System.Enum не имеет прямого отношения наследования с Int32 (хотя оба они ValueType s), поэтому явное приведение не может быть правильным в системе типов

Ответ 2

Я получил его для работы, отбрасывая объект, а затем в int:

public static class EnumExtensions
{
    public static int ToInt(this Enum enumValue)
    {
        return (int)((object)enumValue);
    }
}

Это уродливо и, вероятно, не самый лучший способ. Я буду продолжать возиться с ним, чтобы увидеть, могу ли я придумать что-то лучшее...

EDIT: собирался опубликовать, что Convert.ToInt32 (enumValue) работает так же хорошо, и заметил, что MartinStettner избил меня.

public static class EnumExtensions
{
    public static int ToInt(this Enum enumValue)
    {
        return Convert.ToInt32(enumValue);
    }
}

Тест:

int x = DayOfWeek.Friday.ToInt();
Console.WriteLine(x); // results in 5 which is int value of Friday

EDIT 2: В комментариях кто-то сказал, что это работает только в С# 3.0. Я просто тестировал это в VS2005, как это, и он работал:

public static class Helpers
{
    public static int ToInt(Enum enumValue)
    {
        return Convert.ToInt32(enumValue);
    }
}

    static void Main(string[] args)
    {
        Console.WriteLine(Helpers.ToInt(DayOfWeek.Friday));
    }

Ответ 3

Зачем вам нужно изобретать колесо с помощью вспомогательного метода? Это совершенно законно, чтобы присвоить значение enum его базовому типу.

Это меньше печатает, и, на мой взгляд, более читаемо, чтобы использовать...

int x = (int)DayOfWeek.Tuesday;

... а не что-то вроде...

int y = Converter.ToInteger(DayOfWeek.Tuesday);
// or
int z = DayOfWeek.Tuesday.ToInteger();

Ответ 4

Если вам нужно преобразовать любое перечисление в его базовый тип (не все перечисления поддерживаются int), вы можете использовать:

return System.Convert.ChangeType(
    enumValue,
    Enum.GetUnderlyingType(enumValue.GetType()));

Ответ 5

Из моего ответа здесь:

Учитывая e как в:

Enum e = Question.Role;

Затем эти работы:

int i = Convert.ToInt32(e);
int i = (int)(object)e;
int i = (int)Enum.Parse(e.GetType(), e.ToString());
int i = (int)Enum.ToObject(e.GetType(), e);

Последние два являются уродливыми. Первый должен быть более читабельным, хотя второй - намного быстрее. Или может быть метод расширения - лучший, лучший из обоих миров.

public static int GetIntValue(this Enum e)
{
    return e.GetValue<int>();
}

public static T GetValue<T>(this Enum e) where T : struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>
{
    return (T)(object)e;
}

Теперь вы можете позвонить:

e.GetValue<int>(); //or
e.GetIntValue();

Ответ 6

Кастинг от System.Enum до int отлично работает для меня (он также находится на MSDN). Возможно, это ошибка Resharper.

Ответ 7

Не забывайте, что сам тип Enum содержит множество статических вспомогательных функций. Если все, что вы хотите сделать, - это преобразовать экземпляр enum в соответствующий ему целочисленный тип, тогда литье, вероятно, является наиболее эффективным способом.

Я думаю, что ReSharper жалуется, потому что Enum не является перечислением какого-либо определенного типа, а сами перечисления производятся из скалярного valueetype, а не Enum. Если вам требуется адаптируемое кастинг в общем виде, я бы сказал, что это может вам хорошо подобрать (обратите внимание, что сам тип перечисления также включен в общий файл:

public static EnumHelpers
{
    public static T Convert<T, E>(E enumValue)
    {
        return (T)enumValue;
    }
}

Затем это можно использовать следующим образом:

public enum StopLight: int
{
    Red = 1,
    Yellow = 2,
    Green = 3
}

// ...

int myStoplightColor = EnumHelpers.Convert<int, StopLight>(StopLight.Red);

Я не могу сказать наверняка с головы, но приведенный выше код может даже поддерживаться выводами типа С#, позволяя следующее:

int myStoplightColor = EnumHelpers.Convert<int>(StopLight.Red);