在c#中将字符串转换为枚举值的最佳方法是什么?

我有一个包含枚举值的HTML选择标记。当页面被发布时,我想获取值(将以字符串的形式)并将其转换为相应的枚举值。

在理想的情况下,我可以这样做:

StatusEnum MyStatus = StatusEnum.Parse("Active");

但这不是有效的代码。


当前回答

如果你想在null或空时使用默认值(例如,当从配置文件检索时,该值不存在),并在字符串或数字不匹配任何enum值时抛出异常。不过要注意提莫的回答(https://stackoverflow.com/a/34267134/2454604)。

    public static T ParseEnum<T>(this string s, T defaultValue, bool ignoreCase = false) 
        where T : struct, IComparable, IConvertible, IFormattable//If C# >=7.3: struct, System.Enum 
    {
        if ((s?.Length ?? 0) == 0)
        {
            return defaultValue;
        }

        var valid = Enum.TryParse<T>(s, ignoreCase, out T res);

        if (!valid || !Enum.IsDefined(typeof(T), res))
        {
            throw new InvalidOperationException(
                $"'{s}' is not a valid value of enum '{typeof(T).FullName}'!");
        }
        return res;
    }

其他回答

对于性能,这可能会有所帮助:

    private static Dictionary<Type, Dictionary<string, object>> dicEnum = new Dictionary<Type, Dictionary<string, object>>();
    public static T ToEnum<T>(this string value, T defaultValue)
    {
        var t = typeof(T);
        Dictionary<string, object> dic;
        if (!dicEnum.ContainsKey(t))
        {
            dic = new Dictionary<string, object>();
            dicEnum.Add(t, dic);
            foreach (var en in Enum.GetValues(t))
                dic.Add(en.ToString(), en);
        }
        else
            dic = dicEnum[t];
        if (!dic.ContainsKey(value))
            return defaultValue;
        else
            return (T)dic[value];
    }

您正在寻找枚举。解析。

SomeEnum enum = (SomeEnum)Enum.Parse(typeof(SomeEnum), "EnumValue");

在。net Core和。net Framework≥4.0中,有一个通用的解析方法:

Enum.TryParse("Active", out StatusEnum myStatus);

这也包括c# 7的新内联变量,因此它执行try-parse,转换为显式枚举类型,并初始化+填充myStatus变量。

如果你能使用c# 7和最新的。net,这是最好的方法。

原来的答案

在。net中,它相当丑陋(直到4或以上):

StatusEnum MyStatus = (StatusEnum) Enum.Parse(typeof(StatusEnum), "Active", true);

我倾向于将其简化为:

public static T ParseEnum<T>(string value)
{
    return (T) Enum.Parse(typeof(T), value, true);
}

然后我可以这样做:

StatusEnum MyStatus = EnumUtil.ParseEnum<StatusEnum>("Active");

评论中建议的一个选项是添加一个扩展,这很简单:

public static T ToEnum<T>(this string value)
{
    return (T) Enum.Parse(typeof(T), value, true);
}

StatusEnum MyStatus = "Active".ToEnum<StatusEnum>();

最后,如果字符串不能被解析,你可能想要使用一个默认enum:

public static T ToEnum<T>(this string value, T defaultValue) 
{
    if (string.IsNullOrEmpty(value))
    {
        return defaultValue;
    }

    T result;
    return Enum.TryParse<T>(value, true, out result) ? result : defaultValue;
}

这就要求:

StatusEnum MyStatus = "Active".ToEnum(StatusEnum.None);

然而,我会小心地添加这样的扩展方法到字符串(没有命名空间控制),它将出现在字符串的所有实例上,无论它们是否持有enum(因此1234.ToString(). toenum (statusenume . none)将是有效的,但毫无意义)。通常最好避免用只应用于非常特定的上下文的额外方法来混淆微软的核心类,除非您的整个开发团队都非常了解这些扩展的作用。

这里的大多数答案都要求您在每次调用扩展方法时始终传递枚举的默认值。如果你不想采用这种方法,你可以像下面这样实现它:

 public static TEnum ToEnum<TEnum>(this string value) where TEnum : struct
 {
     if (string.IsNullOrWhiteSpace(value))
          return default(TEnum);

     return Enum.TryParse(value, true, out TEnum result) ? result : default(TEnum);

 }

使用默认文字(可从c# 7.1获得)

 public static TEnum ToEnum<TEnum>(this string value, TEnum defaultValue = default) where TEnum : struct
 {
       if (string.IsNullOrWhiteSpace(value))
            return defaultValue ;

       return Enum.TryParse(value, true, out TEnum result) ? result : defaultValue ;

 }

更好的是:

public static TEnum ToEnum<TEnum>(this string value) where TEnum : struct
{
      if (string.IsNullOrWhiteSpace(value))
           return default;

      return Enum.TryParse(value, true, out TEnum result) ? result : default;

}

我使用了class(具有解析和性能改进的Enum强类型版本)。我在GitHub上找到了它,它应该也适用于。net 3.5。它有一些内存开销,因为它缓冲了一个字典。

StatusEnum MyStatus = Enum<StatusEnum>.Parse("Active");

这篇博文是Enums - NET 3.5中更好的语法,更好的性能和TryParse。

和代码: https://github.com/damieng/DamienGKit/blob/master/CSharp/DamienG.Library/System/EnumT.cs