鉴于下面的代码,int
演员是否有可能抛出异常?
static void foo(Type typeEnum)
{
if (typeEnum.IsEnum)
{
foreach (var enumVal in Enum.GetValues(typeEnum))
{
var _val = (int)enumVal;
}
}
}
答案 0 :(得分:5)
是的,如果enum
支持类型不是int
,例如:
public enum X : long
{
A,
B,
C
}
这将抛出。这是因为enum
值是object
的框,并且您不能将'object'强制转换为'int',除非包含的值实际上是'int'。
您可以通过执行适用于Convert.ToInt32()
或更小的所有支持类型的int
来缓解此问题:
static void foo(Type typeEnum)
{
if (typeEnum.IsEnum)
{
foreach (var enumVal in Enum.GetValues(typeEnum))
{
var _val = Convert.ToInt32(enumVal);
}
}
}
或者,如果您想假设int
并且更安全,可以检查enum
的基础类型:
if (Enum.GetUnderlyingType(typeEnum) != typeof(int))
{
throw new ArgumentException("This method only accepts int enums.");
}
或者,您可以假设long
如果已签名,则ulong
如果未签名(您可以包含负enum
值,但往往更少见):
static void foo(Type typeEnum)
{
if (typeEnum.IsEnum)
{
foreach (var enumVal in Enum.GetValues(typeEnum))
{
var _val = Convert.ToInt64(enumVal);
}
}
}
这就是为什么做出一些假设并在通话中检查它们可能更安全。你打算取消装箱值的任何东西都有可能抛出或溢出。
您甚至可以通用并让用户传递他们想要的类型:
static IEnumerable<ToType> foo<ToType>(Type typeEnum)
{
if (typeEnum.IsEnum)
{
foreach (var enumVal in Enum.GetValues(typeEnum))
{
yield return (ToType)Convert.ChangeType(enumVal, typeof(ToType));
}
}
}
所以你可以调用它:
IEnumerable<int> values foo<int>(typeof(YourEnum));
然后,如果他们得到一个例外,它就落在他们身上以指定正确的尺寸类型......
答案 1 :(得分:2)
Enums是奇怪的野兽。他们可能会继承很久而且仍然是枚举。
我很确定如果你采用这样做的枚举,这个理论代码会引发一个强制转换异常。
答案 2 :(得分:0)
正如James Michael Hare所提到的,枚举可以是long
。但是,使用Convert.ToInt32
不够好,因为您仍然可以获得溢出异常。想象一下,以下枚举的值大于甚至可以适合int:
public enum BigEnum : long
{
BigValue = (long)int.MaxValue + 5
}
在这种情况下,无法将该值转换为int
,因为它太大了。但是,您可以使用这样的逻辑,它不会抛出:
static void foo(Type typeEnum)
{
var underlyingType = Enum.GetUnderlyingType(typeEnum);
if (typeEnum.IsEnum)
{
foreach (var enumVal in Enum.GetValues(typeEnum))
{
var _val = Convert.ChangeType(enumVal, underlyingType);
}
}
}
它使用Enum.GetUnderlyingType
方法确保对ChangeType
的调用将使用正确的类型。 (事实上,GetUnderlyingType的MSDN页面的示例代码几乎完成了我的示例代码所做的事情。)
答案 3 :(得分:0)
Enum.GetValues
实际上返回该特定枚举类型的数组。
未提及的是,如果int[]
或TEnum:int
(基元的CLR数组无论签名是否可转换),特定数组也可转换为TEnum:uint
否则要防守你总是可以使用Convert.ChangeType(object,Type)
api来保证安全。
因此,您可以将代码编写为:
static void foo(Type typeEnum)
{
if (typeEnum.IsEnum)
{
var array = Enum.GetValues(typeEnum)
int[] arrayAsInts = array as int[];
if(arrayAsInts != null)
{
foreach (var enumVal in arrayAsInts)
{
var _val = enumVal;
}
}
else
{
foreach (var enumVal in array)
{
var _val = Convert.ChangeType(enumVal,typeof(int));
}
}
}
}