Thanks to this question I managed to work out how to constrain my generic method to accept only enums.
感谢这个问题,我设法解决了如何限制我的泛型方法只接受枚举。
Now I'm trying to create a generic method so that I can bind a drop-down to any enum I choose, displaying the description in the drop-down, with the value equal to the numeric value of the enum value.
现在我正在尝试创建一个泛型方法,以便我可以将下拉列表绑定到我选择的任何枚举,在下拉列表中显示描述,其值等于枚举值的数值。
public static object EnumToDataSource<T>() where T : struct, IConvertible {
if (!typeof(T).IsEnum) // just to be safe
throw new Exception(string.Format("Type {0} is not an enumeration.", typeof(T)));
var q = Enum.GetValues(typeof(T)).Cast<T>()
.Select(x => new { ID = DataUtil.ToByte(x), Description = x.ToString() }) // ToByte() is my own method for safely converting a value without throwing exceptions
.OrderBy(x => x.Description);
return q;
}
Looks nice, but ToByte() always returns 0, even if my enumeration has values explicitly set, like so:
看起来不错,但ToByte()总是返回0,即使我的枚举有明确设置的值,如下所示:
public enum TStatus : byte {
Active = 1,
Inactive = 0,
}
Outside the generic method, if I cast a value of type TStatus
to byte
, it works perfectly. Inside the generic method, if I try cast something of type T
to byte
I get a compiler error. I can't find anything in the Enum static interface to do this, either.
在泛型方法之外,如果我将类型为TStatus的值转换为byte,则它可以完美地工作。在泛型方法中,如果我尝试将类型为T的东西转换为字节,则会出现编译错误。我也无法在Enum静态界面中找到任何内容来执行此操作。
So, how do I get the numeric value of the enum inside the generic? (I'll also accept any other advice about optimizing my code gratefully...)
那么,如何在泛型中获取枚举的数值? (我也会接受有关优化代码的任何其他建议......)
Edit: Um, er... turns out that the thing wasn't working... because there was a bug in my ToByte() method... (blush). Oh well, thanks anyway - I learned a lot from this!
编辑:嗯,呃...事实证明事情不起作用...因为我的ToByte()方法中有一个错误......(脸红)。哦,不管怎样,谢谢 - 我从中学到了很多东西!
4 个解决方案
#1
You can do it like this (change DataUtil.ToByte(x) to x.ToByte(null)):
你可以这样做(将DataUtil.ToByte(x)更改为x.ToByte(null)):
public static object EnumToDataSource<T>() where T : struct, IConvertible
{
if (!typeof (T).IsEnum) throw new Exception(string.Format("Type {0} is not an enumeration.", typeof (T)));
var q =
Enum.GetValues(typeof (T)).Cast<T>().Select(x => new {ID = x.ToByte(null), Description = x.ToString()}).OrderBy(
x => x.Description).ToArray();
return q;
}
#2
I think the simplest thing to do is use the Convert class instead of a cast:
我认为最简单的方法是使用Convert类而不是强制类:
T someValueThatIsAnEnum;
byte enumValue = Convert.ToByte( (object)someValueThatIsAnEnum );
Alternatively, you can rely on the fact that enums can convert themselves to a string representation, and parse themselves back as well:
或者,您可以依赖以下事实:枚举可以将自身转换为字符串表示形式,并将其自身解析回来:
T someValueThatIsAnEnum;
string enumAsString = someValueThatIsAnEnum.ToString();
byte enunValue = (byte)Enum.Parse( typeof(T), enumAsString );
#3
I use the following utility function to convert an enum type to a hashtable that's bindable. It also regexes camel case names to space seperated words.
我使用以下实用程序函数将枚举类型转换为可绑定的哈希表。它还将骆驼案例名称用于空格分隔词。
public static Hashtable BindToEnum(Type enumType)
{
// get the names from the enumeration
string[] names = Enum.GetNames(enumType);
// get the values from the enumeration
Array values = Enum.GetValues(enumType);
// turn it into a hash table
Hashtable ht = new Hashtable(names.Length);
for (int i = 0; i < names.Length; i++)
// Change Cap Case words to spaced Cap Case words
// note the cast to integer here is important
// otherwise we'll just get the enum string back again
ht.Add(
(int)values.GetValue(i),
System.Text.RegularExpressions.Regex.Replace(names[i], "([A-Z0-9])", " $1", System.Text.RegularExpressions.RegexOptions.Compiled).Trim()
);
// return the dictionary to be bound to
return ht;
}
You could easily adapt this to be a generic function by taking the top of what you put in your question and changing the definition of the function.
您可以通过在问题中添加顶部并更改函数的定义,轻松地将其调整为通用函数。
#4
Maybe you can do something with my EnumExtensions
也许你可以用我的EnumExtensions做点什么
foreach on an enum and create a datasource.
foreach on enum并创建数据源。
#1
You can do it like this (change DataUtil.ToByte(x) to x.ToByte(null)):
你可以这样做(将DataUtil.ToByte(x)更改为x.ToByte(null)):
public static object EnumToDataSource<T>() where T : struct, IConvertible
{
if (!typeof (T).IsEnum) throw new Exception(string.Format("Type {0} is not an enumeration.", typeof (T)));
var q =
Enum.GetValues(typeof (T)).Cast<T>().Select(x => new {ID = x.ToByte(null), Description = x.ToString()}).OrderBy(
x => x.Description).ToArray();
return q;
}
#2
I think the simplest thing to do is use the Convert class instead of a cast:
我认为最简单的方法是使用Convert类而不是强制类:
T someValueThatIsAnEnum;
byte enumValue = Convert.ToByte( (object)someValueThatIsAnEnum );
Alternatively, you can rely on the fact that enums can convert themselves to a string representation, and parse themselves back as well:
或者,您可以依赖以下事实:枚举可以将自身转换为字符串表示形式,并将其自身解析回来:
T someValueThatIsAnEnum;
string enumAsString = someValueThatIsAnEnum.ToString();
byte enunValue = (byte)Enum.Parse( typeof(T), enumAsString );
#3
I use the following utility function to convert an enum type to a hashtable that's bindable. It also regexes camel case names to space seperated words.
我使用以下实用程序函数将枚举类型转换为可绑定的哈希表。它还将骆驼案例名称用于空格分隔词。
public static Hashtable BindToEnum(Type enumType)
{
// get the names from the enumeration
string[] names = Enum.GetNames(enumType);
// get the values from the enumeration
Array values = Enum.GetValues(enumType);
// turn it into a hash table
Hashtable ht = new Hashtable(names.Length);
for (int i = 0; i < names.Length; i++)
// Change Cap Case words to spaced Cap Case words
// note the cast to integer here is important
// otherwise we'll just get the enum string back again
ht.Add(
(int)values.GetValue(i),
System.Text.RegularExpressions.Regex.Replace(names[i], "([A-Z0-9])", " $1", System.Text.RegularExpressions.RegexOptions.Compiled).Trim()
);
// return the dictionary to be bound to
return ht;
}
You could easily adapt this to be a generic function by taking the top of what you put in your question and changing the definition of the function.
您可以通过在问题中添加顶部并更改函数的定义,轻松地将其调整为通用函数。
#4
Maybe you can do something with my EnumExtensions
也许你可以用我的EnumExtensions做点什么
foreach on an enum and create a datasource.
foreach on enum并创建数据源。