2009-04-14 3 views
4

Ich habe beschlossen, es unmöglich ist, die folgenden (äquivalent) Enum-Operationen über Reflexion zu tun - wie die Enum-Klasse keine Operatoren hat, und auch nicht die emittierte Code keine Betreiber ausgesetzt:Erhalten Integralwert von Boxed Enum

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

Also habe ich zur Zeit die folgenden (äquivalent) tue:

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

der gut arbeitet, ist das einzige Problem, dass der entsprechende Code der boxedEnum in eine ganze Zahl zu drehen ist:

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

Welcher bin ich sicher, dass Sie zustimmen werden, ist schrecklich und hacky.

Also diese Frage hat zwei Zinken. Es wäre toll, wenn jemand mir einen Fehler beweisen und ein Mittel zur Verfügung stellen könnte, um binäre Operationen an Box-Enums durchzuführen - andernfalls wäre jeder Weg, den String-Round-Trip zu vermeiden, geschätzt.

Guffa gab mir, was ich brauchte, um die Enum zu einem bestimmten Typ zu konvertieren. Ich verfasste eine Erweiterungsmethode, die die Nitty-gritties tut:

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

Antwort

6

Ein Boxed-Wert kann niemals geändert werden. Sie müssen nur die Enum unbox, um den Betrieb zu tun und es Kasten wieder:

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

Edit:

Vorausgesetzt, dass der zugrunde liegende Typ des ENUM-int ist, können Sie einfach es unbox es in int und Kasten zu int. Der Box-Int kann später auf den Enum-Typ entpackt werden:

boxedEnum = (int)boxedEnum & ~2; 

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

Leider kann ich nicht. Es ist eine Hilfsmethode, die jede Art von Enum akzeptieren muss. –

+0

Vorausgesetzt, dass der zugrunde liegende Typ der Enumeration int ist, können Sie es einfach in int entpacken und es in int einbetten. Der Box-Int kann später zum Enum-Typ entpackt werden. – Guffa

+0

@Guffa du Genie! Können Sie Ihre Antwort so bearbeiten, dass ich sie bitte annehmen kann? –

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

Haben Sie so etwas erreichen?

+0

Die Enum ist boxed. Sie müssen es auspacken, bevor Sie es an einen int übergeben. –