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

其他回答

object Enum.Parse(System.Type enumType, string value, bool ignoreCase);

如果你有一个名为mood的enum,它会像这样:

   enum Mood
   {
      Angry,
      Happy,
      Sad
   } 

   // ...
   Mood m = (Mood) Enum.Parse(typeof(Mood), "Happy", true);
   Console.WriteLine("My mood is: {0}", m.ToString());

注意,enuml . parse()的性能并不理想,因为它是通过反射实现的。(枚举. tostring()也是如此,它是反过来的。)

如果你需要在性能敏感的代码中将字符串转换为枚举,最好的方法是在启动时创建Dictionary<String,YourEnum>,并使用它来进行转换。

不确定什么时候添加的,但在Enum类上现在有一个

Parse<TEnum>(stringValue)

与问题中的例子一起用:

var MyStatus = Enum.Parse<StatusEnum >(“Active”)

或者忽略大小写:

var MyStatus = Enum.Parse<StatusEnum >(“active”, true)

下面是它使用的反编译方法:

    [NullableContext(0)]
    public static TEnum Parse<TEnum>([Nullable(1)] string value) where TEnum : struct
    {
      return Enum.Parse<TEnum>(value, false);
    }

    [NullableContext(0)]
    public static TEnum Parse<TEnum>([Nullable(1)] string value, bool ignoreCase) where TEnum : struct
    {
      TEnum result;
      Enum.TryParse<TEnum>(value, ignoreCase, true, out result);
      return result;
    }

我喜欢扩展方法的解决方案。

namespace System
{
    public static class StringExtensions
    {

        public static bool TryParseAsEnum<T>(this string value, out T output) where T : struct
        {
            T result;

            var isEnum = Enum.TryParse(value, out result);

            output = isEnum ? result : default(T);

            return isEnum;
        }
    }
}

下面是我的测试实现。

using static Microsoft.VisualStudio.TestTools.UnitTesting.Assert;
using static System.Console;

private enum Countries
    {
        NorthAmerica,
        Europe,
        Rusia,
        Brasil,
        China,
        Asia,
        Australia
    }

   [TestMethod]
        public void StringExtensions_On_TryParseAsEnum()
        {
            var countryName = "Rusia";

            Countries country;
            var isCountry = countryName.TryParseAsEnum(out country);

            WriteLine(country);

            IsTrue(isCountry);
            AreEqual(Countries.Rusia, country);

            countryName = "Don't exist";

            isCountry = countryName.TryParseAsEnum(out country);

            WriteLine(country);

            IsFalse(isCountry);
            AreEqual(Countries.NorthAmerica, country); // the 1rst one in the enumeration
        }

你现在可以使用扩展方法了:

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>();