如何在C#的switch语句中使用枚举类型的字符串值?

75

我已定义了一个 C# 枚举,如下:

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;
  ...

我原本以为枚举类型是常量。我该怎么解决这个问题?

(由于某些值超出了范围,我无法将值解析为枚举类型)

12个回答

187
自从C# 6推出,你可以使用:case nameof(SomeEnum.SomeValue): Nameof在编译时被评估,只是将给定变量、类型或成员的(未限定的)名称转换为字符串。自然地,如果您重命名枚举选项名称,它也会相应地更改。

1
太好了。我想在编译时使用枚举的字符串值(在属性中),这个解决方案对我很有帮助。 - shox
谢谢!干净且时尚。谢谢! - ChristianProgrammer

47

将您的switch语句中的字符串转换为枚举值。

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

1
那不会处理空值比较,但是这种边缘情况可以在 case 语句之外处理。 - John Fisher
字符串值 = null; //"partial01"; ORDER? order = value == null? null : (ORDER?)Enum.Parse(typeof(ORDER), value, true); - Richard Anthony Freeman-Hein

33

枚举是一个常量,但.ToString()的结果不是。 对于编译器而言,它是一个动态值。 你可能需要将你的switch case转换为一系列的if / else语句。


32

作为使用if .. else的另一种选择,您可以首先将字符串转换为枚举。但是如果选项数量很少,则可能没有太多意义:

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
}

*叹气*如果只有一个内置的T Enum.Parse<T>(string value)和TryParse版本就好了 :)


4
Enum.TryParse<T>(string value, out T result)是一个枚举类型的方法,用于将字符串转换为指定的枚举值。它在.NET Framework 4.5中被添加,因此在写作时不可用。 - Rune FS
switch ((ORDER)Enum.Parse(typeof(ORDER), value))) 缺少一个结束的“)”符号。 - Enrico

17
你将此设计作为枚举的原因,但实际上你并没有真正地使用它作为枚举。为什么要将枚举值转换为字符串然后在switch语句中使用,而不是直接使用枚举?
你说你无法将其解析为枚举,因为一些值超出了枚举范围。那么应该问的问题是,“为什么?”如果允许未定义的值存在,那枚举的意义何在?当收到未定义的值时,您希望发生什么?如果对于任何未定义的值都是相同的操作,那么可以使用默认情况。如果不是,则可以包括与数字表示相匹配的其他case。
如果您确实返回字符串,则可能不想使用枚举。相反,您需要创建一个公共静态类,其中包含公共字符串常量,然后您可以在switch语句中使用它们。这里的技巧是评估将以区分大小写的方式进行。
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;
}

(您可能还希望清理您的大小写格式。)

有时只检查枚举值,有时涉及更广泛的值范围。我同意这可能是一个混乱的设计,以后可能会消失。 - peter.murray.rust
@peter.murray.rust:你实际上得到的是什么类型的值?你总是得到字符串值还是数字值?如果是数字值,保留枚举,将其作为枚举值进行切换,并具有默认情况或其他标记的情况,以匹配“额外”值并执行适当的工作。如果是字符串,则采用我展示的方法,并拥有一个保存字符串表示的静态类。您仍然可以添加其他标记的情况以匹配“额外”值。归根结底,枚举只有在您想要给数字值“友好”或有意义的名称时才真正有用。 - Scott Dorman

6
正如Thorarin所指出的,如果您的switch语句只包含enum案例,请先将您的string转换为enum。至少在.Net框架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;
}

2
枚举值是常量,但您正在尝试使用方法的结果(ORDER.partial01.ToString()),而不是常量。在我看来,最好的选择是改用if / else if / else语句,而不是switch。这将允许您使用所需的逻辑。
或者,如果您将字符串切换为枚举值,则可以直接切换枚举值。但是,您不能在一个switch中切换枚举值+ null +其他字符串。

如果使用ORDER,你可以开启null,但不能使用字符串。 - Richard Anthony Freeman-Hein

1
使用扩展程序
      public static string ToGender(this Gender enumValue)
        {
            switch (enumValue)
            {
                case Gender.Female:
                    return "Female";
                case Gender.Male:
                    return "Male";
                default:
                    return null;
            }
        }

例子

Gender.Male.ToGender();

1

枚举是常量,但ToString()是返回值的函数。 根据调用它的枚举对象的实例。

也就是说,这两个语句:

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

调用相同的函数,但返回两个不同的值,因此对函数 .ToString() 的调用本身不是一个常量值。


1

对于编译器而言,这不是一个静态值,因为它是一个函数调用:

ORDER.partial01.ToString()

因此,您不能在case语句中使用它作为比较。但是,您可以简单地这样做:

case "partial01"

这样做是可行的,因为枚举值和字符串是相同的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接