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

C# 将字符串严格解析为枚举的最佳方法是什么?,c#,enums,C#,Enums,假设我有一个枚举: public enum MyEnum { OptionOne = 0, OptionTwo = 2, OptionThree = 4 } 正如问题中所说,我使用enum.parse方法从字符串解析enum: public class Enumer { public static MyEnum? ParseEnum(string input) { try { return (MyE

假设我有一个枚举:

public enum MyEnum
{
    OptionOne = 0,
    OptionTwo = 2,
    OptionThree = 4
}
正如问题中所说,我使用
enum.parse
方法从字符串解析enum:

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,不管它是否超出范围

解析的最佳方式是什么:

  • 仅将“MyEnum.OptionOne”、“MyEnum.OptionTwo”、“MyEnum.optionTree”的字符串值放入对应的枚举中
  • 字符串“MyEnum.OptionOne”、“MyEnum.optionwo”、“MyEnum.optionTree”以及0、2和4的值分别输入MyEnum.OptionOne、MyEnum.optionwo和MyEnum.optionTree

  • 类似问题的链接对提供的测试没有帮助-它仍然将字符串转换为整数,即使它们不在枚举范围内。

    您可以使用
    enum.GetValues(Type enumType)
    自己执行此操作

    公共静态MyEnum?ParseEnum(字符串输入)
    {
    return(MyEnum?)Enum.GetValues(typeof(MyEnum)).OfType()的值
    .FirstOrDefault(v=>v.ToString()==输入);
    }
    
    添加对还可以添加的整数的支持

    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));
    }
    
    公共静态MyEnum?ParseEnum(字符串输入)
    {
    int值;
    var isInt=int.TryParse(输入,输出值);
    return(MyEnum?)Enum.GetValues(typeof(MyEnum)).OfType()的值
    .FirstOrDefault(v=>v.ToString()==输入
    ||(isInt&(int)v==值);
    }
    
    由于我不是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));
    }
    
    publicstatict?ParseEnum(字符串输入)
    其中T:struct
    {
    int值;
    var isInt=int.TryParse(输入,输出值);
    返回类型()的枚举.GetValues(typeof(T))
    .FirstOrDefault(v=>v.ToString()==typeof(T).Name+input
    ||(isInt&(int)v==值);
    }
    
    据我所知,@ErkanDemirel可能是重复的,这个问题是关于Enum.Parse()语法本身的。@Kolky你误解了这个问题。我不想将“12345”解析为12345,但是Enum.parse会这样做。我觉得你没有读这篇文章。对不起,误读了你的上一条语句。首先将其转换为Enum,然后检查作用域不是更有效吗?请检查Enum方法
    parse()
    IsDefined()
    使用反射,因为枚举只不过是一个带有
    public const int OptionOne=1
    字段的类。因此,这应该具有相同的性能。如果要有效地执行此操作,应创建
    IDictionary
    IDictionary
    ,并将其用于转换。
    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));
    }