C# 不管C中的底层类型如何,系统枚举值的一般处理#

C# 不管C中的底层类型如何,系统枚举值的一般处理#,c#,.net,C#,.net,我实现了一个将两个枚举值作为参数的方法: void HandleEnumValue( System.Enum v, System.Enum bits ) 两个参数的实际枚举类型不一定相同 在这个方法中,我假设枚举的底层类型是int。 现在,首次使用具有 只要是基础类型,该方法就会抛出异常 我喜欢增强该方法,以便它可以接受任何枚举值,而不必考虑 基础类型的。我有一个实现,但我不喜欢 非常感谢 我想知道是否有更通用/可维护的解决方案? 唉,我不能使用泛型类型参数,因为这会引入 破坏库中的更改,以及

我实现了一个将两个枚举值作为参数的方法:

void HandleEnumValue( System.Enum v, System.Enum bits )
两个参数的实际枚举类型不一定相同

在这个方法中,我假设枚举的底层类型是int。 现在,首次使用具有 只要是基础类型,该方法就会抛出异常

我喜欢增强该方法,以便它可以接受任何枚举值,而不必考虑 基础类型的。我有一个实现,但我不喜欢 非常感谢

我想知道是否有更通用/可维护的解决方案?

唉,我不能使用泛型类型参数,因为这会引入 破坏库中的更改,以及对我的方法的无数调用 必须更换

下面是代码和我的不太好的解决方案:

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 ...
    }

}

在.NET 4中,添加了一个方法,它几乎可以实现您想要的功能:

不幸的是,如果实际的枚举类型不同,此方法会引发错误。它的实现非常容易复制,无需进行枚举类型检查,或者如果您使用的是较旧版本的框架:

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

此方法将处理任何类型的枚举和任何基础类型,即使它们不同。

不确定是否有帮助,但这非常感谢!您的实现的类型转换要少得多,而且看起来比我的好得多,尽管它仍然具有打开类型代码语句。我希望这能以某种方式避免。OTTH开关可能会被修复一段时间,Int128类型仍然是一些年后的道路。。。