Подтвердить что ты не робот

Преобразование целого числа в тип перечислимого типа, только известного во время выполнения

Предположим, что у нас есть перечисление:

enum Foo { A=1,B=2,C=3 }

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

static int GetValue() { return 2; }
...
Foo foo = (Foo)GetValue(); // becomes Foo.B

И бокс дает поле типа Foo:

object o1 = foo;
Console.WriteLine(o1.GetType().Name); // writes Foo

(и действительно, вы можете вставить как Foo и unbox как int, или поле как int и unbox как Foo довольно счастливо)

Однако (проблема); если тип перечисления известен только во время выполнения, вещи... сложнее. Очевидно, тривиально помещать его как int - но могу ли я вставить его как Foo? (В идеале без использования дженериков и MakeGenericMethod, что было бы уродливо). Convert.ChangeType выдает исключение. ToString и Enum.Parse работает, но ужасно неэффективен.

Я мог бы посмотреть на определенные значения (Enum.GetValues или Type.GetFields), но это очень сложно для [Flags], и даже без этого потребуется сначала вернуться к первому типу (что не так сложно, к счастью).

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

4b9b3361

Ответ 1

Я думаю, что метод Enum.ToObject сделает то, что вы хотите.

Type type= typeof(Foo);
object o1 = Enum.ToObject(type,GetValue());

Ответ 2

Просто хотел добавить что-то к @aaronb answer: мне нужно было сделать это для некоторого кода авто-сопоставления и выяснил, что мне нужно сделать несколько проверок чтобы код работал для произвольных типов. В частности, нулевые значения и обнуляемые перечисления будут давать вам головные боли.

Самый надежный код, который у меня есть на данный момент:

static object CastBoxedValue(object value, Type destType)
{
    if (value == null)
        return value;

    Type enumType = GetEnumType(destType);
    if (enumType != null)
        return Enum.ToObject(enumType, value);

    return value;
}

private static Type GetEnumType(Type type)
{
    if (type.IsEnum)
        return type;

    if (type.IsGenericType)
    {
        var genericDef = type.GetGenericTypeDefinition();
        if (genericDef == typeof(Nullable<>))
        {
            var genericArgs = type.GetGenericArguments();
            return (genericArgs[0].IsEnum) ? genericArgs[0] : null;
        }
    }
    return null;
}

Если вы никогда не можете иметь тип с нулевым значением, просто игнорируйте это.:)