如何在泛型方法中获取枚举的数据值?

发布于 2024-07-27 15:19:12 字数 1235 浏览 3 评论 0原文

感谢这个问题我设法弄清楚如何约束我的通用方法只接受枚举。

现在我正在尝试创建一个通用方法,以便我可以将下拉列表绑定到我选择的任何枚举,在下拉列表中显示描述,其值等于数字值枚举值。

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;
}

看起来不错,但 ToByte() 始终返回 0,即使我的枚举显式设置了值,如下所示:

public enum TStatus : byte {
  Active = 1,
  Inactive = 0,
}

在泛型方法之外,如果我将 TStatus 类型的值强制转换为 byte,它工作完美。 在泛型方法中,如果我尝试将 T 类型的内容转换为 byte,则会出现编译器错误。 我在 Enum 静态接口中也找不到任何可以执行此操作的内容。

那么,如何获取泛型内枚举的数值呢? (我也会感激地接受有关优化我的代码的任何其他建议...)

编辑: 嗯,呃...结果证明这件事不起作用...因为有一个错误在我的 ToByte() 方法中...(脸红)。 哦,好吧,无论如何,谢谢 - 我从中学到了很多东西!

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:

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.

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一页 2024-08-03 15:19:12

我认为最简单的方法是使用 Convert 类而不是强制转换:

T someValueThatIsAnEnum;
byte enumValue = Convert.ToByte( (object)someValueThatIsAnEnum );

或者,您可以依赖枚举可以将自身转换为字符串表示形式,并解析自身:

T someValueThatIsAnEnum;
string enumAsString = someValueThatIsAnEnum.ToString();
byte enunValue = (byte)Enum.Parse( typeof(T), enumAsString );

I think the simplest thing to do is use the Convert class instead of a cast:

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 );
灰色世界里的红玫瑰 2024-08-03 15:19:12

您可以这样做(将 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;
        }

You can do it like this (change DataUtil.ToByte(x) to 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;
        }
祁梦 2024-08-03 15:19:12

我使用以下实用函数将枚举类型转换为可绑定的哈希表。 它还使用正则表达式驼峰命名法来分隔单词。

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;
}

通过在问题中添加内容并更改函数的定义,您可以轻松地将其调整为通用函数。

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.

我一向站在原地 2024-08-03 15:19:12

也许你可以用我的 EnumExtensions

foreach 在枚举上 做一些事情并创建一个数据源。

Maybe you can do something with my EnumExtensions

foreach on an enum and create a datasource.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文