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

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

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

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

但这不是有效的代码。


当前回答

在。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 T ToEnum<T>(this string value, bool ignoreCase = true)
{
    return (T) Enum.Parse(typeof (T), value, ignoreCase);
}

你可以通过下面的代码调用它们(在这里,FilterType是一个枚举类型):

FilterType filterType = type.ToEnum<FilterType>();

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

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

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

 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;

}

你必须使用Enum。解析从Enum中获取对象值,之后你必须将对象值更改为特定的Enum值。转换为enum值可以通过使用Convert.ChangeType来实现。请看下面的代码片段

public T ConvertStringValueToEnum<T>(string valueToParse){
    return Convert.ChangeType(Enum.Parse(typeof(T), valueToParse, true), typeof(T));
}
public static T ParseEnum<T>(string value)            //function declaration  
{
    return (T) Enum.Parse(typeof(T), value);
}

Importance imp = EnumUtil.ParseEnum<Importance>("Active");   //function call

==================== 一个完整的程序 ====================

using System;

class Program
{
    enum PetType
    {
    None,
    Cat = 1,
    Dog = 2
    }

    static void Main()
    {

    // Possible user input:
    string value = "Dog";

    // Try to convert the string to an enum:
    PetType pet = (PetType)Enum.Parse(typeof(PetType), value);

    // See if the conversion succeeded:
    if (pet == PetType.Dog)
    {
        Console.WriteLine("Equals dog.");
    }
    }
}
-------------
Output

Equals dog.