【问题标题】:Get Integral Value of Boxed Enum获取盒装枚举的积分值
【发布时间】:2009-04-14 19:08:08
【问题描述】:

我已经决定不可能通过反射来执行以下(等效)枚举操作 - 因为 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);

我相信你会同意这是可怕的和 hacky。

所以这个问题有两个方面。如果有人能证明我错了,并提供一种对盒装枚举执行二进制操作的方法,那就太棒了——否则任何避免字符串往返的方法都会受到赞赏。

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();
        }
    }

【问题讨论】:

    标签: c# reflection enums


    【解决方案1】:

    装箱的值永远不能原地更改。您只需将枚举拆箱,执行操作并再次将其装箱:

    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
    

    【讨论】:

    • 不幸的是我不能。它是一个辅助方法,需要接受任何类型的枚举。
    • 假设枚举的底层类型是int,你可以把它拆箱成int,装箱成int。装箱的 int 稍后可以拆箱为枚举类型。
    • @Guffa 你这个天才!您能否编辑您的答案,以便我接受。
    【解决方案2】:
    int enumValue = (int)SomeEnum.Val1 | (int)SomeEnum.Val2;
    SomeEnum e = (SomeEnum)enumValue;
    

    你想实现这样的目标吗?

    【讨论】:

    • 枚举是装箱的。在转换为 int 之前,您必须将其拆箱。
    猜你喜欢
    • 1970-01-01
    • 2022-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-03
    • 1970-01-01
    • 2010-09-17
    • 2010-12-20
    相关资源
    最近更新 更多