获得盒装枚举的积分值

时间:2009-04-14 09:43:10

标签: c# reflection enums

我已经决定不可能通过反射执行以下(等效的)枚举操作 - 因为Enum类没有运算符,并且发出的代码也没有公开任何运算符:

object boxedEnum = MyEnum.Flag1 | MyEnum.Flag2;
boxedEnum &= ~MyEnum.Flag2; // Remove the flag.

所以我目前正在做以下(等效):

int boxedEnumValue = (int) boxedEnum;
boxedEnumValue &= ~MyEnum.Flag2;
boxedEnum = Enum.ToObject(boxedEnum.GetType(), boxedEnumValue);

哪个工作正常,唯一的问题是将boxedEnum转换为整数的等效代码是:

int boxedEnumValue = int.Parse(Enum.Format(boxedEnum.GetType(), boxedEnum, "X"), System.Globalization.NumberStyles.HexNumber);

我相信你会同意的是可怕和骇客。

所以这个问题有两个方面。如果有人可以证明我错了并提供在盒装枚举上执行二进制操作的方法,这将是非常棒的 - 否则任何避免字符串往返的方法都将受到赞赏。

Guffa向我提供了将枚举转换为特定类型所需的内容。我编写了一个执行细节的扩展方法:

    /// <summary>
    /// Gets the integral value of an enum.
    /// </summary>
    /// <param name="value">The enum to get the integral value of.</param>
    /// <returns></returns>
    public static T ToIntegral<T>(this object value)
    {
        if(object.ReferenceEquals(value, null))
            throw new ArgumentNullException("value");
        Type rootType = value.GetType();
        if (!rootType.IsEnum)
            throw new ArgumentOutOfRangeException("value", "value must be a boxed enum.");
        Type t = Enum.GetUnderlyingType(rootType);

        switch (t.Name.ToUpperInvariant())
        {
            case "SBYTE":
                return (T)Convert.ChangeType((sbyte) value, typeof(T));
            case "BYTE":
                return (T) Convert.ChangeType((byte) value, typeof(T));
            case "INT16":
                return (T) Convert.ChangeType((Int16) value, typeof(T));
            case "UINT16":
                return (T) Convert.ChangeType((UInt16) value, typeof(T));
            case "INT32":
                return (T) Convert.ChangeType((Int32) value, typeof(T));
            case "UINT32":
                return (T) Convert.ChangeType((UInt32) value, typeof(T));
            case "INT64":
                return (T) Convert.ChangeType((Int64) value, typeof(T));
            case "UINT64":
                return (T) Convert.ChangeType((UInt64) value, typeof(T));
            default:
                throw new NotSupportedException();
        }
    }

2 个答案:

答案 0 :(得分:6)

永远不能更改盒装值。您只需要取消装入枚举,执行操作并再次装箱:

boxedEnum = (MyEnum)boxedEnum & ~MyEnum.Flag2;

编辑:

如果枚举的基础类型是int,则只需将其解包为int并将其设置为int即可。盒装的int稍后可以取消装入枚举类型:

boxedEnum = (int)boxedEnum & ~2;

MyEnum value = (MyEnum)boxedEnum; // works both for a boxed int and a boxed MyEnum

答案 1 :(得分:0)

int enumValue = (int)SomeEnum.Val1 | (int)SomeEnum.Val2;
SomeEnum e = (SomeEnum)enumValue;

你想要达到这样的目标吗?