General handling of System.Enum values ​​regardless of base type in C #

I implemented a method that takes two Enum values ​​as parameters:

void HandleEnumValue( System.Enum v, System.Enum bits ) 

The actual type of enumeration is not necessarily the same for the two parameters.

In this method, I assumed that the base enumeration type is int. Now for the first time this method is called with enumeration values ​​that are long as the base type, and the method now throws an exception.

I like to improve the method so that it can accept any enum value, regardless of the underlying type. I have an implementation for this, but I don't like it very much.

I wonder if there is a more general / supported solution?

Alas, I can’t use the type parameter, because this would lead to a violation of changes in the library and the number of calls to my method would have to be replaced.

Here's the code and my not-so-good solution:

 using System; [Flags()] public enum ByteEnum : byte { One = 1, SomeByte = 0x42 } [Flags()] public enum ShortEnum: short{ One = 1, SomeShort = 0x4223 } [Flags()] public enum IntEnum : int { One = 1, SomeInt = 0x42230815 } [Flags()] public enum LongEnum : long { One = 1, SomeLong = 0x4223081547112012L } public class Program { public static void Main() { HandleEnumValue( ByteEnum.SomeByte, ByteEnum.One ) ; HandleEnumValue( ShortEnum.SomeShort, ShortEnum.One ) ; HandleEnumValue( IntEnum.SomeInt, IntEnum.One ) ; HandleEnumValue( LongEnum.SomeLong, LongEnum.One ) ; // will throw InvalidCastException: HandleEnumValueOriginal( ByteEnum.SomeByte, ByteEnum.One ) ; // will throw InvalidCastException: HandleEnumValueOriginal( ShortEnum.SomeShort, ShortEnum.One ) ; HandleEnumValueOriginal( IntEnum.SomeInt, IntEnum.One ) ; // will throw InvalidCastException: HandleEnumValueOriginal( LongEnum.SomeLong, LongEnum.One ) ; } // new implementation, that I dislike. static void HandleEnumValue( System.Enum v, System.Enum bits ) { // assert underlying types of v and bits are equal if ( v.GetTypeCode() != bits.GetTypeCode() ) throw new Exception( "enum type code mismatch" ) ; bool hasBitsSet = false ; // won't compile: bool hasBitsSet = ( ( v & bits ) == bits ) ; long lvalue = 0L ; // will throw : lvalue = (long)(object)v switch ( v.GetTypeCode() ) { case TypeCode.Byte : hasBitsSet = ( ( (byte)(object)v & (byte)(object)bits ) == (byte)(object)bits ) ; lvalue = (long)(byte)(object)v ; break ; case TypeCode.Int16 : hasBitsSet = ( ( (short)(object)v & (short)(object)bits ) == (short)(object)bits ) ; lvalue = (long)(short)(object)v ; break ; case TypeCode.Int32 : hasBitsSet = ( ( (int)(object)v & (int)(object)bits ) == (int)(object)bits ) ; lvalue = (long)(int)(object)v ; break ; case TypeCode.Int64 : hasBitsSet = ( ( (long)(object)v & (long)(object)bits ) == (long)(object)bits ) ; lvalue = (long)(object)v ; break ; } Console.WriteLine( "(new) enum value = " + v.ToString() ) ; Console.WriteLine( "(new) number value = " + lvalue.ToString() ) ; Console.WriteLine( "(new) has bits set = " + hasBitsSet.ToString() ) ; // further processing ... } // original implementation, that doesn't work anymore static void HandleEnumValueOriginal( System.Enum v, System.Enum bits ) { int lvalue = (int)(object)v ; bool hasBitsSet = ( ( (int)(object)v & (int)(object)bits ) == (int)(object)bits ) ; Console.WriteLine( "(original) enum value = " + v.ToString() ) ; Console.WriteLine( "(original) number value = " + lvalue.ToString() ) ; Console.WriteLine( "(original) has bits set = " + hasBitsSet.ToString() ) ; // further processing ... } } 
+4
source share
1 answer

.NET 4 has an added method that does almost what you want: Enum.HasFlag .

Unfortunately, this method throws if the actual types of enumerations are different. Its implementation is quite simple for replication without checking the type of enumeration, or if you are using an older version of the framework:

 static void HandleEnumValue(Enum v, Enum bits) { ulong enumValue = ToUInt64(v); ulong bitsValue = ToUInt64(bits); bool hasBitsSet = (enumValue & bitsValue) == bitsValue; Console.WriteLine("enum value = " + v); Console.WriteLine("number value = " + bits); Console.WriteLine("has bits set = " + hasBitsSet); } internal static ulong ToUInt64(Enum value) { switch (Convert.GetTypeCode(value)) { case TypeCode.SByte: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: return (ulong) Convert.ToInt64(value); case TypeCode.Byte: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: return Convert.ToUInt64(value); default: throw new ArgumentOutOfRangeException("value"); } } 

This method will handle any type of enumeration and any base type, even if they are different.

+4
source

All Articles