严格将字符串解析为枚举的最佳方法是什么?

时间:2016-04-11 15:30:16

标签: c# enums

假设我有一个枚举:

public enum MyEnum
{
    OptionOne = 0,
    OptionTwo = 2,
    OptionThree = 4
}

就像在How should I convert a string to an enum in C#?问题中所说的那样,我使用Enum.Parse方法从字符串解析枚举:

public class Enumer
{
    public static MyEnum? ParseEnum(string input)
    {
        try
        {
            return (MyEnum) Enum.Parse(typeof (MyEnum), input);
        }
        catch (ArgumentException)
        {
            return null;
        }
    }

}

不幸的是,它不能按预期使用整数,表示为字符串 我不希望Parse.Enum()从字符串转换int,但实际上它是。
一个简单的测试:

[TestClass]
public class Tester
{
    [TestMethod]
    public void TestEnum()
    {
        Assert.AreEqual(MyEnum.OptionTwo, Enumer.ParseEnum("OptionTwo"));
        Assert.IsNull(Enumer.ParseEnum("WrongString"));
        Assert.IsNull(Enumer.ParseEnum("2")); // returns 2 instead of null
        Assert.IsNull(Enumer.ParseEnum("12345")); // returns 12345 instead of null
    }
}

只能通过两次四次检查 Enumer.ParseEnum("2")返回MyEnum.OptionTwo而不是null 此外,Enumer.ParseEnum("12345")返回12345,无论它是否超出范围。

解析的最佳方法是什么:

  1. 只将“MyEnum.OptionOne”,“MyEnum.OptionTwo”,“MyEnum.OptionThree”的字符串值放入其枚举对应项中。
  2. 将“MyEnum.OptionOne”,“MyEnum.OptionTwo”,“MyEnum.OptionThree”和0,2和4的值分别分别放入MyEnum.OptionOne,MyEnum.OptionTwo,MyEnum.OptionThree?
  3. 类似问题How should I convert a string to an enum in C#?的链接对提供的测试没有帮助 - 它仍然将字符串转换为整数,即使它们不在枚举范围内。

1 个答案:

答案 0 :(得分:5)

您可以使用Enum.GetValues(Type enumType)

自行完成此操作
public static MyEnum? ParseEnum(string input)
{
    return (MyEnum?) Enum.GetValues(typeof(MyEnum)).OfType<object>()
                         .FirstOrDefault(v => v.ToString() == input);
}

添加对整数的支持,您也可以添加。

public static MyEnum? ParseEnum(string input)
{
    int value;
    var isInt = int.TryParse(input, out value);
    return (MyEnum?) Enum.GetValues(typeof(MyEnum)).OfType<object>()
                         .FirstOrDefault(v => v.ToString() == input
                                           || (isInt & (int)v == value));
}

由于我不能100%确定您的上一个要求,因此我添加了一个包含该名称且更通用的

public static T? ParseEnum<T>(string input)
    where T : struct 
{
    int value;
    var isInt = int.TryParse(input, out value);
    return (T?)Enum.GetValues(typeof(T)).OfType<object>()
                   .FirstOrDefault(v => v.ToString() == typeof(T).Name + input
                                    || (isInt & (int)v == value));
}