I have the following code. I need it to create a List
of KeyValuePair<string, string>
with the name and value of each enum value in the specified enum type.
public static List<KeyValuePair<string, string>> GetEnumList<TEnum>() where TEnum : struct
{
if (!typeof(TEnum).IsEnum)
throw new ArgumentException("Type must be an enumeration");
List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
foreach (TEnum e in Enum.GetValues(typeof(TEnum)))
list.Add(new KeyValuePair<string, string>(e.ToString(), ((int)e).ToString()));
return list;
}
However, the expression ((int)e).ToString()
generates the following error.
Cannot convert type 'TEnum' to 'int'
I'm just trying to cast an enum instance to an integer. Can anyone tell me why this won't work?
EDIT:
I tried this version:
enum Fruit : short
{
Apple,
Banana,
Orange,
Pear,
Plum,
}
void Main()
{
foreach (var x in EnumHelper.GetEnumList<Fruit>())
Console.WriteLine("{0}={1}", x.Value, x.Key);
}
public static List<KeyValuePair<string, string>> GetEnumList<TEnum>() where TEnum : struct
{
if (!typeof(TEnum).IsEnum)
throw new ArgumentException("Type must be an enumeration");
List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
foreach (TEnum e in Enum.GetValues(typeof(TEnum)))
{
list.Add(new KeyValuePair<string, string>(e.ToString(), ((int)(dynamic)e).ToString()));
}
return list;
}
But this gives me the error:
Cannot convert type 'System.Enum' to 'int'
TEnum
is - per constraint - a struct. It isn't guaranteed to be an enum.
However, because you are enforcing that constraint at runtime, you can utilize the fact the each enum implements IConvertible
:
foreach (IConvertible e in Enum.GetValues(typeof(TEnum)))
{
list.Add(new KeyValuePair<string, string>(
e.ToString(),
e.ToType(
Enum.GetUnderlyingType(typeof(TEnum)),
CultureInfo.CurrentCulture).ToString()));
}
Other approaches which all have downsides are:
You can first cast to object
and then to int
.
Please note that this will fail at runtime if the underlying type of the enum is anything other than int
.
This can be overcome by casting to dynamic
before casting to int
:
((int)(dynamic)e).ToString()
However, this again has some problems:
If the enum is of type long
, ulong
or uint
it will return incorrect values. You can reduce the problem by casting to ulong
instead of int
but that will still return invalid values for negative enum values.
The only safe way to do this, without nowing the base type, is to use the methods created for it! The methods inside the Enum-class. Even you could try to make use of the IConvertable
interface.
// Get underlying type, like int, ulong, etc.
Type underlyingType = Enum.GetUnderlyingType(typeof(T);
// Convert the enum to that type.
object underlyingValue = e.ToType(underlyingType, null);
// Convert that value to string.
string s = underlyingValue.ToString();
Or in short:
string s = e.ToType(Enum.GetUnderlyingType(typeof(T)), null).ToString();
You can implement it in your code like this:
public static List<KeyValuePair<string, string>> GetEnumList<TEnum>()
where TEnum : struct, IConvertible
{
if (!typeof(TEnum).IsEnum)
throw new ArgumentException("Type must be an enumeration");
List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
foreach (TEnum e in Enum.GetValues(typeof(TEnum)))
{
list.Add(new KeyValuePair<string, string>
(
e.ToString(),
e.ToType(Enum.GetUnderlyingType(typeof(TEnum)), null).ToString()
));
}
return list;
}
If you do not want to use IConvertable
, try to use the Convert
class:
string s = Convert.ChangeType(e, Enum.GetUnderlyingType(typeof(TEnum))).ToString();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With