Yes, if the enum backing type is not int, like:
public enum X : long
{
A,
B,
C
}
This will throw. This is because the enum values are boxes as object, and you can't cast 'object' to 'int' unless the contained value is actually an 'int'.
You could alleviate this by doing a Convert.ToInt32() which will work for all backing types of int or smaller:
static void foo(Type typeEnum)
{
if (typeEnum.IsEnum)
{
foreach (var enumVal in Enum.GetValues(typeEnum))
{
var _val = Convert.ToInt32(enumVal);
}
}
}
Or, if you want to assume int and just be safer, you can check the underlying type of the enum like:
if (Enum.GetUnderlyingType(typeEnum) != typeof(int))
{
throw new ArgumentException("This method only accepts int enums.");
}
Alternatively, you could assume a type of long if signed or ulong if unsigned (you can have negative enum values, but tend to be rarer):
static void foo(Type typeEnum)
{
if (typeEnum.IsEnum)
{
foreach (var enumVal in Enum.GetValues(typeEnum))
{
var _val = Convert.ToInt64(enumVal);
}
}
}
This is why it's probably safer to make some assumptions and check them on the call. Anything you do to unbox the value has the potential of throwing or overflowing.
You could even go generic and have the user pass in the type they want to get out:
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));
}
}
}
So you could invoke this:
IEnumerable<int> values foo<int>(typeof(YourEnum));
Then if they get an exception, it falls on them to specify the right size type...
GetValuesreturns an array. Implicitly typing could mean the compiler will chooseobjectwhich can't be directly cast toint. Why not remove the implicitvarand save yourself the headache?foreachthen. You can cast fromobjecttointas long as theobjectis truly boxing anint, just can't do a conversion cast.var. The compiler will happily insert casts that would normally be explicit and can fail at runtime without telling you. In particular in this case using anintiteration variable will compile and fail at runtime in the same cases in which this code fails. [Once again the lack of generics in .net 1 caused warts in C#]