Преобразование строк в enum в С#
У меня есть поле со списком, в котором я показываю некоторые записи, например:
Equals
Not Equals
Less Than
Greater Than
Обратите внимание, что эти строки содержат пробелы. У меня есть перечисление, которое соответствует этим элементам, например:
enum Operation{Equals, Not_Equals, Less_Than, Greater_Than};
Так как пространство недопустимо, я использовал символ _.
Теперь, есть ли способ преобразовать заданную строку автоматически в элемент перечисления без написания цикла или набора условий if, которые я сам в С#?
Ответы
Ответ 1
Я предлагаю создать Dictionary<string, Operation>
для сопоставления дружественных имен константам перечисления и использовать обычные соглашения об именах в самих элементах.
enum Operation{ Equals, NotEquals, LessThan, GreaterThan };
var dict = new Dictionary<string, Operation> {
{ "Equals", Operation.Equals },
{ "Not Equals", Operation.NotEquals },
{ "Less Than", Operation.LessThan },
{ "Greater Than", Operation.GreaterThan }
};
var op = dict[str];
В качестве альтернативы, если вы хотите придерживаться своего текущего метода, вы можете сделать (что я рекомендую не делать):
var op = (Operation)Enum.Parse(typeof(Operation), str.Replace(' ', '_'));
Ответ 2
Либо создайте выделенный картограф, используя словарь (на ответ Мехрдада), либо внесите TypeConverter.
Пользовательский TypeConverter может либо заменить " " -> "_"
(и наоборот), либо он может отражать перечисление и использовать атрибут для определения отображаемого текста элемента.
enum Operation
{
[DisplayName("Equals")]
Equals,
[DisplayName("Not Equals")]
Not_Equals,
[DisplayName("Less Than")]
Less_Than,
[DisplayName("Greater Than")]
Greater_Than
};
public class OperationTypeConverter : TypeConverter
{
private static Dictionary<string, Operation> operationMap;
static OperationTypeConverter()
{
BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.GetField
| BindingFlags.Public;
operationMap = enumType.GetFields(bindingFlags).ToDictionary(
c => GetDisplayName(c)
);
}
private static string GetDisplayName(FieldInfo field, Type enumType)
{
DisplayNameAttribute attr = (DisplayNameAttribute)Attribute.GetCustomAttribute(typeof(DisplayNameAttribute));
return (attr != null) ? attr.DisplayName : field.Name;
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
string stringValue = value as string;
if (stringValue != null)
{
Operation operation;
if (operationMap.TryGetValue(stringValue, out operation))
{
return operation;
}
else
{
throw new ArgumentException("Cannot convert '" + stringValue + "' to Operation");
}
}
}
}
Эта реализация может быть улучшена несколькими способами:
Ответ 3
Operation enumVal = (Operation)Enum.Parse(typeof(Operation), "Equals")
Для "Не равных" вам необходимо заменить пробелы символами подчеркивания в приведенном выше выражении
EDIT: следующая версия заменяет пробелы символами подчеркивания перед попыткой разбора:
string someInputText;
var operation = (Operation)Enum.Parse(typeof(Operation), someInputText.Replace(" ", "_"));
Ответ 4
Вы можете использовать метод Parse:
Operarion operation = (Operation)Enum.Parse(typeof(Operation), "Not_Equals");
Некоторые примеры здесь
Ответ 5
Зачем использовать другой способ: конвертировать перечисление в строку?
Просто сгенерируйте элементы вашего поля со списком из списка.
Ответ 6
в С#, вы можете добавить методы расширения для типов перечисления. Видеть
http://msdn.microsoft.com/en-us/library/bb383974.aspx
Вы можете использовать этот подход для добавления методов toString (Операция op), fromString (String str) и toLocalizedString (Операция op) к вашим типам перечислений. Метод, который вы используете для поиска конкретной строки, зависит от вашего приложения и должен соответствовать тому, что вы делаете в подобных случаях. Использование словаря, как предложили другие, кажется хорошим первым подходом, если вам не нужна полная локализация в вашем приложении.
Ответ 7
Я бы использовал одноэлемент этого enum mapper class, который работает намного быстрее, чем Enum.Parse(который использует отражение и очень медленный).
Затем вы можете использовать EnumFromString(typeof(YourEnum), "stringValue")
для получения вашего перечисления.
Ответ 8
Начиная с С# 8 вы можете сделать это с помощью переключателей. В вашем примере я считаю, что код будет таким.
enum Operation{Equals, Not_Equals, Less_Than, Greater_Than};
public static string OperationString(Operation opString) =>
opString switch
{
Operation.Equals => "Equals",
Operation.Not_Equals => "Not Equals",
Operation.Less_Than=> "Less Than",
Operation.Greater_Than=> "Greater Than",
_ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(opString )),
};
Смотрите здесь для документации.