.NET C# switch语句中的字符串比较和枚举比较的区别

7

我很关注样式和性能问题。我的选择是要么执行以下操作之一(抱歉格式不佳,但是这个网站的接口并非所见即所得):

一:

string value = "ALPHA";

switch ( value.ToUpper() )
{
   case "ALPHA":
     // do somthing
     break;
   case "BETA":
     // do something else
     break;
   default:
     break;
}

二:

public enum GreekLetters
{
    UNKNOWN= 0,
    ALPHA= 1,
    BETA = 2,
    etc...

}

string value = "Alpha";
GreekLetters letter = (GreekLetters)Enum.Parse( typeof( GreekLetters ), value.ToUpper() );

switch( letter )
{
   case GreekLetters.ALPHA:
      // do something
      break;
   case GreekLetters.BETA:
      // do something else
      break;
   default:
      break;
}

个人而言,我更喜欢下面的第二个选项,但除了基本的样式原因外,我没有任何真正的理由。 然而,我甚至不确定是否真的有样式上的原因。感谢您的意见。


这会是一个很好的面试问题。我建议你通过分析来确定,因为它取决于 Enum.Parse() 的性能。当然,第二个选项从打字错误的角度来看更容易维护,即使性能相当。 - Rowland Shaw
将枚举值为0的标记为“未知”,并给予+1。 - Cylon Cat
6个回答

9
第二个选项略微更快,因为第一个选项可能需要进行完整的字符串比较。然而,在大多数情况下,差异太小,无法测量。
第二个选项的真正优势在于,您明确了value的有效值仅限于一个狭窄的范围内。实际上,如果字符串值不在预期范围内,它将在Enum.Parse处抛出异常,这往往正是您想要的。

第二个选项较慢,因为它需要反射命中来收集所有字段,然后逐项比较。我在我的答案中指向框架源代码以证明这一点。 - Jeff Moser

4

选项#1更快,因为如果你查看代码 Enum.Parse,你会发现它逐一检查每个项目,寻找匹配项。此外,需要维护和保持一致的代码更少。

一个警告是你不应该使用ToUpper,而应该使用ToUpperInvariant(),因为存在土耳其测试问题。

如果您坚持使用选项#2,请至少使用允许您指定忽略大小写的重载。这比自己转换为大写字母要快。此外,请注意框架设计准则鼓励所有枚举值都使用PascalCase而不是SCREAMING_CAPS。

2
说真的,SCREAMING_CAPS 真的是太 C++ 了。 - Neil N

2

关于性能方面的问题,我无法发表评论,但是就样式而言,我更喜欢选项#2。每当我有一个已知的值集并且该集合相对较小(少于几十个),我更喜欢使用枚举。我发现枚举比字符串值集合更容易处理,而且任何查看代码的人都可以快速了解允许的值集。


2

实际上这取决于枚举中的项数,您需要为每种特定情况进行测试 - 尽管这不太可能有很大的差异。但这是一个很好的问题。

少量值时,Enum.Parse会比任何一个示例都要花费更多时间,因此第二个示例应该会更慢。

有足够的值时,switch语句将被实现为哈希表,它应该与字符串和枚举一样快,因此再次,Enum.Parse可能会使第二个解决方案变慢,但相对而言不会慢太多。

在中间某个位置,我预计比较字符串的成本高于比较枚举,这将使第一个解决方案更快。

我甚至不会惊讶于不同编译器版本或不同选项的结果不同。


1
我肯定会选择第一种方法。Enum.Parse() 会引起相对昂贵的反射操作。此外,如果枚举未定义,Enum.Parse() 将抛出异常,而且由于没有 TryParse() 方法,你需要将其包装在 Try/Catch 块中。

0

不确定在使用字符串值和枚举时是否存在性能差异。

需要考虑的一件事是,您是否需要在代码的其他地方使用用于case语句的值。如果是这样,那么使用枚举将更有意义,因为您有一个值的单一定义。也可以使用const字符串。


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