避免给枚举类型的元素提供显式的值

继上一篇“将0值作为枚举的默认值”后,本文继续讲《编写高质量代码改善C#程序的157个建议》一书第8个建议“避免给枚举类型的元素提供显式的值”。喜欢本书请到各大商城购买原书,支持正版。

一般情况下,没有必要给枚举类型的元素提供显式的值。创建枚举的理由之一,就是为了代替使用实际的数值。不正确地为枚举类型的元素设定显式的值,会带来意想不到的错误。

如果为建议7中的枚举类型Week 增加一个元素,代码如下所示:

enum Week
{
  Monday = 1,
  Tuesday = 2,
  ValueTemp,
  Wednesday = 3,
  Thursday = 4,
  Friday = 5,
  Saturday = 6,
  Sunday = 7
}

设想一下 ValueTemp的值会是什么?为了验证结果,我们来看这段代码的输出:

Week week = Week.ValueTemp;
Console.WriteLine(week);
Console.WriteLine(week == Week.Wednesday);

输出为:

Wednesday
True

很遗憾,我们明明为Week赋值为ValueTemp,可是得到的结果却是Wednesday。

事实上,如果为枚举类型显式地赋过值,那么很有可能在下个版本中,你为了某些增加的需要,会为枚举添加元素,在这个时候,就像我们为Week 增加元素ValueTemp一样,极有可能会一不小心增加一个无效值。

上一个建议中已经讲到如果没有为元素显式赋值,编译器会逐个为元素的值+1。当编译器发现元素ValueTemp 的时候,它会自动在Tuesday = 2的基础上+1,所以,实际 ValueTemp的值和Wednesday的值都是3。而枚举本身所包括的枚举元素都是值类型,所以产生了上面的输出。

从上面的例子我们应该已经注意到,枚举元素允许设定重复的值。所以,当我们看到下面这段代码的输出时,应该不会感到吃惊:

enum Temp
{
  Value1 = 1,
  Value2 = 1
}

private static void NewMethod2()
{
  Temp templ = Temp.Value1;
  Temp temp2 = Temp.Value2;
  Console.WriteLine(templ == temp2);
  Console.WriteLine(templ.Equals(temp2));
  Console.WriteLine(templ.CompareTo(temp2));
  Console.WriteLine(templ == Temp.Value1);
  Console.WriteLine(templ == Temp.Value2);
}

输出为:

True
True
0
True
True

注意 本建议也有例外。例如,当为一个枚举类型指定System.FlagsAttribute 属性时,就意味着可以对这些值执行AND、OR、NOT和 XOR按位运算,这样一来,就要求枚举的每个元素的值都是2的若干次幂,指数依次递增。如Week 的版本就应该为:

[Flags]
enum Week
{
  None = 0x0,
  Monday = 0x1,
  Tuesday = 0x2,
  Wednesday = 0x4,
  Thursday = 0x8,
  Friday = 0x10,
  Saturday = 0x20,
  Sunday = 0x40
}

class MyClass
{
  Week week = Week.Thursday | Week.Sunday;
}

下一篇我们接着读"建议9:习惯重载运算符",欢迎关注微信公众号【小市民在西河】。

原文出处:微信公众号【小市民在西河】

原文链接:

本文观点不代表Dotnet9立场,转载请联系原作者。

发表评论

登录后才能评论