2016-04-11 2 views
4

Скажем, у меня есть перечисление:Каков наилучший способ строго проанализировать строку для перечисления?

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 соответственно?

ссылка на подобный вопрос How should I convert a string to an enum in C#? не помогает с тестом при условии - она ​​по-прежнему преобразует строки в виде целых чисел, даже когда они находятся вне сферы перечислений.

+1

Возможный дубликат [Как преобразовать строку в перечисление в C#?] (http://stackoverflow.com/questions/16100/how-do-i-convert-a-string-to-an-enum-in-c) –

+0

@ErkanDemirel, насколько я понимаю, это вопрос был о самом синтаксисе Enum.Parse(). – enkryptor

+0

@ Kolky вы неправильно поняли вопрос. Я НЕ хочу анализировать «12345» как 12345, но Enum.Parse делает это. – enkryptor

ответ

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)); 
} 
+0

Не было бы более эффективным сначала преобразовать в перечисление, а затем проверить область? – enkryptor

+0

AFAIK методы enum 'Parse()' и 'IsDefined()' используют отражение, поскольку перечисление - это не что иное, как класс с 'public const int OptionOne = 1'. Поэтому это должно иметь одинаковую производительность. Если вы хотите сделать это эффективно, вы должны создать 'IDictionary и' IDictionary 'и использовать это для преобразования. – Toxantron

Смежные вопросы