我正在构建一个函数来扩展Enum。解析概念

允许在没有找到Enum值的情况下解析默认值 不区分大小写

所以我写下了以下内容:

public static T GetEnumFromString<T>(string value, T defaultValue) where T : Enum
{
    if (string.IsNullOrEmpty(value)) return defaultValue;
    foreach (T item in Enum.GetValues(typeof(T)))
    {
        if (item.ToString().ToLower().Equals(value.Trim().ToLower())) return item;
    }
    return defaultValue;
}

我得到一个错误约束不能是特殊类System.Enum。

很好,但是是否有一种变通方法来允许通用Enum,或者我将不得不模仿Parse函数并将类型作为属性传递,这将强制对代码进行丑陋装箱要求。

以下所有建议都非常感谢,谢谢。

已经确定(我已经离开了循环以保持大小写不敏感-我在解析XML时使用这个)

public static class EnumUtils
{
    public static T ParseEnum<T>(string value, T defaultValue) where T : struct, IConvertible
    {
        if (!typeof(T).IsEnum) throw new ArgumentException("T must be an enumerated type");
        if (string.IsNullOrEmpty(value)) return defaultValue;

        foreach (T item in Enum.GetValues(typeof(T)))
        {
            if (item.ToString().ToLower().Equals(value.Trim().ToLower())) return item;
        }
        return defaultValue;
    }
}

编辑:(2015年2月16日)Christopher currents在下面的MSIL或f#中发布了一个编译器强制类型安全的通用解决方案,非常值得一看,并获得好评。如果解决方案在页面上方出现气泡,我将删除此编辑。

编辑2:(2021年4月13日)自从c# 7.3以来,这个问题已经得到解决和支持,我已经更改了公认的答案,尽管出于学术和历史兴趣,充分阅读顶部的答案是值得的:)


当前回答

有趣的是,显然这在其他语言中是可能的(Managed c++, IL直接)。

引用:

... 这两个约束实际上都产生了有效的IL,如果用其他语言编写,也可以被c#使用(您可以在托管c++或IL中声明这些约束)。

谁知道

其他回答

我一直很喜欢这个(你可以适当修改):

public static IEnumerable<TEnum> GetEnumValues()
{
  Type enumType = typeof(TEnum);

  if(!enumType.IsEnum)
    throw new ArgumentException("Type argument must be Enum type");

  Array enumValues = Enum.GetValues(enumType);
  return enumValues.Cast<TEnum>();
}

有趣的是,显然这在其他语言中是可能的(Managed c++, IL直接)。

引用:

... 这两个约束实际上都产生了有效的IL,如果用其他语言编写,也可以被c#使用(您可以在托管c++或IL中声明这些约束)。

谁知道

现有的答案是正确的c# <=7.2。然而,有一个c#语言的功能请求(绑定到一个corefx功能请求)允许以下;

public class MyGeneric<TEnum> where TEnum : System.Enum
{ }

在撰写本文时,该特性正在语言开发会议上“讨论中”。

EDIT

根据nawfal的信息,这是在c# 7.3中引入的。

编辑2

现在在c# 7.3版本中(发布说明)

样本;

public static Dictionary<int, string> EnumNamedValues<T>()
    where T : System.Enum
{
    var result = new Dictionary<int, string>();
    var values = Enum.GetValues(typeof(T));

    foreach (int item in values)
        result.Add(item, Enum.GetName(typeof(T), item));
    return result;
}

我试着改进了一下代码:

public T LoadEnum<T>(string value, T defaultValue = default(T)) where T : struct, IComparable, IFormattable, IConvertible
{
    if (Enum.IsDefined(typeof(T), value))
    {
        return (T)Enum.Parse(typeof(T), value, true);
    }
    return defaultValue;
}

希望这对你有帮助:

public static TValue ParseEnum<TValue>(string value, TValue defaultValue)
                  where TValue : struct // enum 
{
      try
      {
            if (String.IsNullOrEmpty(value))
                  return defaultValue;
            return (TValue)Enum.Parse(typeof (TValue), value);
      }
      catch(Exception ex)
      {
            return defaultValue;
      }
}