Подтвердить что ты не робот

Преобразование строк в enum в С#

У меня есть поле со списком, в котором я показываю некоторые записи, например:

Equals
Not Equals 
Less Than
Greater Than

Обратите внимание, что эти строки содержат пробелы. У меня есть перечисление, которое соответствует этим элементам, например:

enum Operation{Equals, Not_Equals, Less_Than, Greater_Than};

Так как пространство недопустимо, я использовал символ _.

Теперь, есть ли способ преобразовать заданную строку автоматически в элемент перечисления без написания цикла или набора условий if, которые я сам в С#?

4b9b3361

Ответ 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");
            }
        }
    }
}

Эта реализация может быть улучшена несколькими способами:

  • Сделать его общим
  • Внедрить ConvertTo
  • Поддержка FlagsAttribute

Ответ 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 )),
    };

Смотрите здесь для документации.