2009-04-14 2 views
4

Я решил, что это невозможно сделать операции следующим образом (эквивалент) перечисления с помощью отражения - как класс Enum не имеет операторов, а также не излучаемый код выявят любые операторы:Получить интегральное значение штучной 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 дал мне то, что мне нужно, чтобы преобразовать перечисление в определенный тип. Я автор метода расширения, который делает суровое gritties:

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

ответ

6

Значение в коробке никогда не может быть изменено на месте. Вы просто должны распаковывать на перечисление, сделать операцию и коробка снова:

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

Edit:

При условии, что базовый тип перечисления является INT, вы можете просто распаковать его в целое и поле его к int. После этого коробчатый int может быть распакован в тип перечисления:

boxedEnum = (int)boxedEnum & ~2; 

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

К сожалению, я не могу. Это вспомогательный метод, который должен принимать любой вид перечисления. –

+0

При условии, что базовый тип перечисления является int, вы можете просто распаковать его в int и поместить его в int. После этого boxed int может быть распакован в тип перечисления. – Guffa

+0

@ Guffa вы гений! Можете ли вы отредактировать свой ответ, чтобы я мог его принять. –

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

Вы хотите, чтобы достичь чего-то вроде этого?

+0

Перечисление в коробке. Вы должны распаковать его перед тем, как выполнить кастинг в int. –

Смежные вопросы