Преобразовать строку в перечисление в C #

Короткий ответ

Ключевым моментом является следующее:

  • == между двумя ссылочными типами всегда является ссылочным сравнением. Часто чаще всего, например, с Integer и String, вы хотите использовать equals вместо
  • == между ссылочным типом, а числовой примитивный тип всегда является числовым сравнением. Тип ссылки будет подвергнут распаковке преобразование Unboxing null всегда выбрасывает NullPointerException
  • . Хотя у Java много специальных обработок для String, на самом деле это НЕ примитивный тип

Вышеприведенные утверждения для любого заданного действительного кода Java. С этим пониманием в представленном фрагменте нет никакой несогласованности.


Длинный ответ

Вот соответствующие секции JLS:

[д0] JLS 15.21.3 ссылочных операторов равенства == и !=

Если операнды операции равенства оба либо ссылочного типа или нуль , тогда операция является равенством объекта.

blockquote>

Это объясняет следующее:

Integer i = null;
String str = null;

if (i == null) {   // Nothing happens
}
if (str == null) { // Nothing happens
}
if (str == "0") {  // Nothing happens
}

Оба операнда являются ссылочными типами, и именно поэтому == является сравнительным сравнением равенства.

Это также объясняет следующее:

System.out.println(new Integer(0) == new Integer(0)); // "false"
System.out.println("X" == "x".toUpperCase()); // "false"

Для == для численного равенства по крайней мере один из операнда должен быть числовой тип :

JLS 15.21.1 Операторы числового равенства == и !=

Если операнды оператор равенства являются как числовыми, так и одно числовыми, а другой - с числовым типом, двоичное числовое продвижение n выполняется на операндах. Если продвинутым типом операндов является int или long, то выполняется целочисленный тест равенства; если продвинутый тип равен float or double`, тогда выполняется тест равенства с плавающей запятой.

Обратите внимание, что бинарное числовое продвижение выполняет преобразование набора значений и преобразование распаковки.

blockquote>

Это объясняет:

Integer i = null;

if (i == 0) {  //NullPointerException
}

Вот выдержка из Эффективное Java 2nd Edition, пункт 49: Предпочитают примитивы для примитивов в штучной упаковке :

В общем, используйте примитивы, предпочитая вложенные в бокс примитивы, когда у вас есть выбор. Примитивные типы проще и быстрее. Если вы должны использовать примитивы в штучной упаковке, будьте осторожны! Автобоксинг уменьшает многословие, но не опасность использования примитивов в штучной упаковке. Когда ваша программа сравнивает два вложенных в бокс примитива с оператором ==, это делает сравнение идентичности, которое почти наверняка не то, что вы хотите. Когда ваша программа выполняет смешанные вычисления с использованием примитивов с боксами и unboxed, она делает unboxing, и когда ваша программа делает unboxing, она может бросить NullPointerException. Наконец, когда ваши программные поля вводят примитивные значения, это может привести к дорогостоящим и ненужным созданиям объектов.

blockquote>

Есть места, где у вас нет выбора, кроме как использовать примитивы в штучной упаковке, например. generics, но в противном случае вам следует серьезно подумать, оправдано ли решение использовать бокс-примитивы.

Ссылки

Связанные вопросы

Связанные вопросы

732
задан Mehdi 7 March 2019 в 08:29
поделиться

6 ответов

В.NET Core и.NET> 4 существует универсальный метод синтаксического анализа :

Enum.TryParse("Active", out StatusEnum myStatus);

Это также включает C#7, новый встроенный out переменные, таким образом, это делает синтаксический анализ попытки, преобразование в явный перечислимый тип и initialises+populates myStatus переменная.

, Если у Вас есть доступ к C#7 и последней.NET, это - лучший способ.

Исходный Ответ

В.NET это довольно ужасно (до 4 или выше):

StatusEnum MyStatus = (StatusEnum) Enum.Parse(typeof(StatusEnum), "Active", true);

я склонен упрощать это с:

public static T ParseEnum<T>(string value)
{
    return (T) Enum.Parse(typeof(T), value, true);
}

Тогда я могу сделать:

StatusEnum MyStatus = EnumUtil.ParseEnum<StatusEnum>("Active");

Одна опция, предложенная в комментариях, состоит в том, чтобы добавить расширение, которое достаточно просто:

public static T ToEnum<T>(this string value)
{
    return (T) Enum.Parse(typeof(T), value, true);
}

StatusEnum MyStatus = "Active".ToEnum<StatusEnum>();

Наконец, можно хотеть иметь перечисление по умолчанию, чтобы использовать, если строка не может быть проанализирована:

public static T ToEnum<T>(this string value, T defaultValue) 
{
    if (string.IsNullOrEmpty(value))
    {
        return defaultValue;
    }

    T result;
    return Enum.TryParse<T>(value, true, out result) ? result : defaultValue;
}

, Который делает это вызовом:

StatusEnum MyStatus = "Active".ToEnum(StatusEnum.None);

Однако я был бы тщательным добавлением дополнительного метода как это к string как (без управления пространством имен), появится на всех экземплярах [1 110], содержат ли они перечисление или не (таким образом 1234.ToString().ToEnum(StatusEnum.None) было бы допустимо, но бессмыслен). Это часто быть лучшим постараться не создавать помехи базовым классам Microsoft дополнительными методами, которые только применяются в очень определенных контекстах, если у Вашей всей группы разработчиков нет очень хорошего понимания того, что делают те расширения.

1248
ответ дан Keith 7 March 2019 в 08:29
поделиться

Перечисление. Синтаксический анализ является Вашим другом:

StatusEnum MyStatus = (StatusEnum)Enum.Parse(typeof(StatusEnum), "Active");
15
ответ дан Peter Mortensen 7 March 2019 в 08:29
поделиться
object Enum.Parse(System.Type enumType, string value, bool ignoreCase);

Поэтому, если бы у Вас было перечисление, названное настроением, оно было бы похоже на это:

   enum Mood
   {
      Angry,
      Happy,
      Sad
   } 

   // ...
   Mood m = (Mood) Enum.Parse(typeof(Mood), "Happy", true);
   Console.WriteLine("My mood is: {0}", m.ToString());
17
ответ дан brendan 7 March 2019 в 08:29
поделиться

Вы ищете Перечисление. Синтаксический анализ .

SomeEnum enum = (SomeEnum)Enum.Parse(typeof(SomeEnum), "EnumValue");
83
ответ дан Peter Mortensen 7 March 2019 в 08:29
поделиться
// str.ToEnum<EnumType>()
T static ToEnum<T>(this string str) 
{ 
    return (T) Enum.Parse(typeof(T), str);
}
7
ответ дан Mark Cidade 7 March 2019 в 08:29
поделиться

Обратите внимание, что производительность Enum.Parse() ужасна, потому что она реализована через отражение. (То же верно Enum.ToString, который идет другим путем.)

, Если необходимо преобразовать строки в Перечисления в чувствительном к производительности коде, лучший выбор состоит в том, чтобы создать Dictionary<String,YourEnum> при запуске и использовании что сделать преобразования.

175
ответ дан Noctis 7 March 2019 в 08:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: