c# - valueof重写 - java枚举赋值
通过泛型类中的嵌套枚举反射获取枚举值 (2)
我需要通过反射打印出某些类型的枚举值及其相应的底层值。 这在大多数情况下都可以正常工作。 但是,如果枚举是在泛型类型中声明的,则Enum.GetValues
会抛出以下异常:
[System.NotSupportedException: Cannot create arrays of open type. ]
at System.Array.InternalCreate(Void* elementType, Int32 rank, Int32* pLengths, Int32* pLowerBounds)
at System.Array.CreateInstance(Type elementType, Int32 length)
at System.Array.UnsafeCreateInstance(Type elementType, Int32 length)
at System.RuntimeType.GetEnumValues()
完整的复制代码:
using System;
public class Program
{
public static void Main()
{
var enumType= typeof(Foo<>.Bar);
var underlyingType = Enum.GetUnderlyingType(enumType);
Console.WriteLine(enumType.IsEnum);
foreach(var value in Enum.GetValues(enumType))
{
Console.WriteLine("{0} = {1}", value, Convert.ChangeType(value, underlyingType));
}
}
}
public class Foo<T>
{
public enum Bar
{
A = 1,
B = 2
}
}
这是期望的行为,我如何工作?
构建一个类型对我来说是一个可行的但是不可接受的,因为它会变得太复杂。
构造类型将是一种解决方法,但对我来说是不可接受的,因为它会变得太复杂。
这是获得正常行为的唯一方法。
你可以得到一个开放类型的字段,奇怪的是你可以获得枚举的价值。 您应该尽量避免使用这些值,但可以将它们转换为基础类型。
public static void Main()
{
var enumType = typeof(Foo<>.Bar);
var underlyingType = Enum.GetUnderlyingType(enumType);
foreach(var field in enumType.GetFields(BindingFlags.Public | BindingFlags.Static))
{
var value = field.GetValue(null);
var underlyingValue = Convert.ChangeType(value, underlyingType);
Console.WriteLine($"{field.Name} = {underlyingValue}");
}
}
但是, 更好的解决方案是使用field.GetRawConstantValue()
:
public static void Main()
{
var enumType = typeof(Foo<>.Bar);
foreach(var field in enumType.GetFields(BindingFlags.Public | BindingFlags.Static))
{
Console.WriteLine($"{field.Name} = {field.GetRawConstantValue()}");
}
}
这样,如果CLR被修复以防止产生这种奇怪的值,你的代码就不会破坏。
Foo是所谓的开放类型(A类型没有完全定义,因为它有一个泛型)并且不允许打开类型的数组,你可以通过做模拟它
Array.CreateInstance(typeof(Foo<>), 2)
由于Enum的GetValues依赖于创建数组,因此失败。 你可以改为做
var enumType = typeof(Foo<object>.Bar);
(“对象”是一个虚拟类型,因此您不能使用打开类型)或者执行Jon Skeet建议的操作。