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

Как я могу использовать строковое значение значения перечисления С# в аргументе case?

Я определил перечисление С# как

public enum ORDER
{
    ...
    unknown,
    partial01,
    partial12,
    partial23,
}

и может использовать его значение в виде строки, как в:

            string ss = ORDER.partial01.ToString();

Однако, когда я пытаюсь использовать его в выражении case, он не скомпилируется:

string value = ...
switch (value)
{
    case null:
        break;
    case "s":
        // OK
        break;
    case ORDER.partial01.ToString():
        // compiler throws "a constant value is expected"

        break;
  ...

Я думал, что перечисления - это константы. Как мне обойти это?

(я не могу разобрать значение в перечисление, поскольку некоторые из значений находятся за пределами диапазона)

4b9b3361

Ответ 1

Перечисление является константой, но результат .ToString() не является. Что касается компилятора, это динамическое значение. Вероятно, вам нужно преобразовать ваш случай переключения в ряд операторов if/else

Ответ 2

Преобразуйте строку в свой коммутатор в значение перечисления.

(ORDER)Enum.Parse(typeof(ORDER), value, true);

Ответ 3

В качестве альтернативы использованию if .. else сначала вы можете преобразовать строку в enum. Вероятно, это не имеет большого смысла, если количество опций невелико:

if (Enum.IsDefined(typeof(ORDER), value))
{
    switch ((ORDER)Enum.Parse(typeof(ORDER), value)
    {
        case ORDER.partial01:
            // ... 
            break;
        case ORDER.partial12:
            // etc
    }
}
else
{
    // Handle values not in enum here if needed
}

* sigh *, если только была встроенная T Enum.Parse<T>(string value) и версия TryParse:)

Ответ 4

С С# 6 вы можете использовать: case nameof(SomeEnum.SomeValue):

Nameof оценивается во время компиляции, просто для строки, которая соответствует (неквалифицированному) имени данной переменной, типу или члену. Естественно, он изменяется правильно, если вы когда-либо переименовали имя опции перечисления.

Ответ 5

Вы разработали это как перечисление по какой-либо причине, но на самом деле вы не используете его как перечисление. Почему вы берете значение перечисления и преобразуете его в строку, а затем используете в коммутаторе вместо простого перечисления?

Вы сказали, что вы не можете разобрать это в перечисление, потому что некоторые из значений находятся за пределами диапазона перечисления. Тогда возникает вопрос: "Почему?" В чем смысл перечисления, если вы разрешаете значения, которые не определены? Что вы хотите, чтобы получить значение, которое не определено? Если это значение для любого undefined, то вы можете использовать случай по умолчанию. Если это не так, то вы можете включить дополнительные случаи, которые соответствуют числовому представлению.

Если вы действительно вернете строки, вы, вероятно, не захотите использовать перечисление. Вместо этого вы хотите создать открытый статический класс, содержащий общедоступные строковые константы, которые затем можно использовать в вашем коммутаторе. Трюк здесь заключается в том, что оценка будет проводиться с учетом случая.

public static class Order
{
   public const string Unknown = "Unknown";
   public const string Partial01 = "Partial01";
   public const string Partial12 = "Partial12";
   public const string Partial23 = "Partial23";
}

string value = Order.Partial01
switch (value)
{
   case Order.Partial01:
      break;

    default:
       // Code you might want to run in case you are
       // given a value that doesn't match.
       break;
}

(Вы также можете очистить корпус.)

Ответ 6

Как указал Торарин, если ваш оператор switch может содержать только случаи enum, сначала преобразуйте string в enum. По крайней мере, с .Net framework 4, вы можете использовать метод Enum.TryParse()<TEnum> как определено здесь и сделать что-то вроде:

ORDER orderEnum = ORDER.unknown;
Enum.TryParse<ORDER>(value, out orderEnum);

switch (orderEnum)
{
    case ORDER.unknown:
        // perhaps do something to deal with cases not matching
        // to known enum values, based on the string value
        break;
    case ORDER.partial01:
    case ORDER.partial12:
    case ORDER.partial23:
        // map value to known cases, etc.
        break;
}

Ответ 7

Значения Enum являются константами, но вы пытаетесь использовать результаты метода (ORDER.partial01.ToString()), а не константу.

Лучшим вариантом, на мой взгляд, было бы просто переключить это на использование операторов if/else if/else вместо коммутатора. Это позволит вам использовать желаемую логику.

В качестве альтернативы, если вы переключите свою строку на значение перечисления, вы можете напрямую включить значения перечисления. Вы не можете включить перечисление + нуль + другие строки, хотя в одном коммутаторе.

Ответ 8

Не могли бы вы просто сказать

case "partial01":

?

Ответ 9

перечисления являются постоянными, но ToString() - это функция, возвращающая значение. на основе экземпляра объекта перечисления, на который он вызывается.

Это два утверждения:

ORDER.partial01.ToString()
ORDER.partial02.ToString()

вызывает одну и ту же функцию, но возвращает два разных значения, поэтому вызов функции .ToString() в ней сам не является постоянным значением.

Ответ 10

Это не статическое значение в отношении компилятора, так как это вызов функции:

ORDER.partial01.ToString()

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

case "partial01"

Это будет работать, поскольку значение перечисления и строка идентичны.

Ответ 11

просто вы можете определить глобальную переменную

static ORDER orderstr;

теперь вы можете установить значение orderstr в любом месте страницы

public enum ORDER
{ 
    unknown,
    partial01,
    partial12,
    partial23,
}

switch (orderstr)
{
    case Order.Partial01:
        break;
    default:
        break;
}