将整数转换为仅在运行时已知的盒装枚举类型

Mar*_*ell 42 .net c# reflection enums

想象一下,我们有一个枚举:

enum Foo { A=1,B=2,C=3 }
Run Code Online (Sandbox Code Playgroud)

如果在编译时已知类型,则可以使用直接强制转换来在枚举类型和基础类型之间进行更改(通常int):

static int GetValue() { return 2; }
...
Foo foo = (Foo)GetValue(); // becomes Foo.B
Run Code Online (Sandbox Code Playgroud)

而拳击这给了一个类型的框Foo:

object o1 = foo;
Console.WriteLine(o1.GetType().Name); // writes Foo
Run Code Online (Sandbox Code Playgroud)

(事实上​​,你可以Foo打包和取消打包int,或int打包和取消打开Foo非常愉快)

然而(问题); 如果枚举类型仅在运行时已知,那么事情就更棘手了.把它装成一个显然是微不足道的int- 但是我可以把它装箱Foo吗?(理想情况下,不使用泛型MakeGenericMethod,这将是丑陋的).Convert.ChangeType抛出一个例外.ToString并且Enum.Parse工作,但是非常低效.

我可以查看定义的值(Enum.GetValuesType.GetFields),但这很难[Flags],甚至没有要求首先返回底层类型(谢天谢地,这并不难).

但; 是否更直接从正确的底层类型的值获取到枚举类型的框,其中类型仅在运行时已知?

aar*_*onb 71

我认为这种Enum.ToObject方法会做你想要的.

Type type= typeof(Foo);
object o1 = Enum.ToObject(type,GetValue());
Run Code Online (Sandbox Code Playgroud)

  • 容易错过.看起来像一个可怕的方法名称.像'Enum.FromValue`之类的东西可能会更好. (4认同)
  • 如何| $(*&%$(我错过了!谢谢,这正是我想要的. (3认同)

Aar*_*ght 8

只是想在@ aaronb的答案中添加一些内容:我必须为某些自动映射代码执行此操作,并发现我需要进行多项检查才能使代码适用于任意类型.特别是,null值和可空的枚举会让你头疼.

我目前最简单的代码是:

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;
}
Run Code Online (Sandbox Code Playgroud)

如果你永远不能拥有可空类型,那么就忽略它.:)

  • `Nullable.GetUnderlyingType` 可能比检查泛型参数更直接一些。 (2认同)