Enum.GetName的奇怪行为

时间:2014-02-07 18:08:52

标签: c# .net-4.0 exception-handling enums

我有一个这样的枚举:

public enum MyEnum
{
    Character = 'C',
    Number = 'N',
}

然后我正在做这样的事情:

char myChar = 'C';
var value = Enum.GetName(typeof(MyEnum), myChar); //throw exception on .NET 3.5 or less

此代码在使用.NET 4的项目中正常,但在.NET 3.5或更低版本上引发异常。这是例外:

  

传入的值必须是枚举基础或基础类型   枚举,例如Int32.Parameter name:value

所以我用.NET 4发布了我的项目并与我的朋友分享并告诉他们他们需要.NET4。他们成功地运行程序但是发现程序在某些系统上抛出相同的异常,即使使用.NET 4也是如此!任何人都知道这个异常的原因是什么?

我用这种方式解决了这个问题,但有兴趣知道为什么它在某些系统上工作而不在其他系统上工作? (所有这些都有.NET4)

var value = Enum.GetName(typeof(MyEnum), (int)myChar);

3 个答案:

答案 0 :(得分:8)

这在.NET 4.5中已更改。请注意,很难看到您是否在计算机上安装了4.0或4.5,4.5 替换 4.0并使用与4.0相同的安装目录。

更改的方法是@Dirk引用的方法,即内部IsIntegerType()辅助方法。 4.0版本看起来像这样:

internal static bool IsIntegerType(Type t)
{
    if (((!(t == typeof(int)) && !(t == typeof(short))) && (!(t == typeof(ushort)) && 
          !(t == typeof(byte)))) && ((!(t == typeof(sbyte)) && !(t == typeof(uint))) && 
          !(t == typeof(long))))
    {
        return (t == typeof(ulong));
    }
    return true;
}

注意typeof(char)是如何测试的,所以它不认为它是传递给Enum.GetName()的 value 参数的有效类型。

.NET Framework版本中的这种类型的更改并非并行版本,但它确实很难诊断程序失败。特别是因为您在项目中以.NET 4.0为目标,但最终在安装了4.5的机器上运行,所以从未注意到问题。但kaboom在安装了4.0的机器上。

最好的旋转,它是4.0中的一个错误,他们修复了4.5。坦率地说,你当然希望一个char完全有效,因为那是你用来初始化枚举成员的东西。它确实显示了微软修复错误的难度。

答案 1 :(得分:3)

Enum.GetName的实现已从2.0更改为4.0。

这是2.0(使用ILSpy)的反编译版本:

public static string GetName(Type enumType, object value)
{
    [...]
    // Enum.intType = typeof(int)
    Type type = value.GetType();
    if (type.IsEnum || type == Enum.intType || type == typeof(short) || type == typeof(ushort) || type == typeof(byte) || type == typeof(sbyte) || type == typeof(uint) || type == typeof(long) || type == typeof(ulong))
    {
        return Enum.InternalGetValueAsString(enumType, value);
    }
    throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), "value");
}

您可以看到type = typeof(char)此异常是throw。


对于4.0,它是:

public static string GetName(Type enumType, object value)
{
    [...]
    // this is actually in a method called by GetName, I put it here for clarity
    Type type = value.GetType();
    if (!type.IsEnum && !Type.IsIntegerType(type))
    {
        throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), "value");
    }
    [...]
}

// Type.IsIntegerType
internal static bool IsIntegerType(Type t)
{
    return t == typeof(int) || t == typeof(short) || t == typeof(ushort) || t == typeof(byte) || t == typeof(sbyte) || t == typeof(uint) || t == typeof(long) || t == typeof(ulong) || t == typeof(char) || t == typeof(bool);
}

但是这里type = typeof(char)不会导致异常。

答案 2 :(得分:1)

枚举的已批准类型为byte, sbyte, short, ushort, int, uint, long, or ulong MSDN

您无法创建Enum char值,.NET允许您执行此操作,但是编译器会将您的char值转换为其等效的int表示(ASCII)。