本文共 2015 字,大约阅读时间需要 6 分钟。
最近,我遇到了enum的问题,我想分享一下,以防其他人遇到它。
那enum是什么?
Enums是一个数值常量列表,可以帮助我们处理许多情况,例如某些东西可以有标记或属性,以区别于另一个对象,或者它们代表方法的不同选项。其他时候,它们代表一个对象或关系的状态,例如,我们可以使用Employee enum告诉我们一个人是经理,副总裁,CEO。
但无论我们给enum什么名称,在后台,它只是一个用于代表该状态的数字,如下所示:
enum Foo {Bar1,Bar2,Bar3,}
因此,在本例中,我们声明了一个名为Foo的enum,它可以具有3个值之一,Bar1,隐式地具有0,Bar2,其值为1,Bar3具有值2。
问题在于enum的背景值以及我们如何使用它,例如,因为我们知道Bar2的值为1,我们可以将数字1转换为Foo类型的枚举,我们将得到如下的Bar2:
Console.WriteLine((Foo)1);
//会输出: Bar2
但是既然我们在谈论数字,那么enums也可以映射到这样的特定值:
enum Foo {Bar1 = 2,Bar2,Bar3 = 5,}
基本上,在这种情况下,Bar1将有一个值2, Bar2将具有值3,Bar3并将具有值5。
而现在是奇怪的部分和副作用。
我们可以用enum为同一个值定义两个或多个标识符,如下所示:
enum Foo {Bar1 = 2,Bar2 = 2,Bar3,}
请注意,Bar1和Bar2具有相同的值(不一定是2)。因此,如果我们现在运行以下命令,则运行时不知道我们引用的是哪个标识符,因此它将为中间标识符提供该值:
Console.WriteLine((Foo)2);
//会输出:Bar2因为它是最新的
中间的意思是,即使我们有这样定义的enum,输出也是相同的:
enum Foo {Bar1 = 2,Bar2 = 2,Bar3 = 2,}
所以无论我们如何运行它,输出仍然是Bar2 ,但如果我们有这样的enum定义:
enum Foo {Bar1 = 2,Bar2 = 2,Bar3 = 2,Bar4 = 2,Bar5 = 2,Bar6 = 2,Bar7 = 2}
运行相同的命令将给我们,Bar4因为它是中间的,如果我们的enum数是偶数的,那么它将使我们中间的枚举数接近尾数,所以对于两个enum标识符,它将给我们第二个,三个它会给我们第二个,但是对于四个它将给我们第三个,同样,如果我们有五个相同值的标识符。对于六,它将给我们第三个,依此类推。
但是,当在Bar1之前像这样放置另一个值更低的enum标识符时,会发生什么情况呢?
enum Foo {Bar,Bar1 = 2,Bar2 = 2,Bar3,}
现在,如果我们运行输出命令,它将不会显示enum具有该值的中间值,而是显示中间值 - 1所以在这种情况下,它将显示Bar1和前一个enum,但是让我们更进一步来看看这个枚举:
enum Foo {Bar,Bar1 = 2,Bar2 = 2,Bar3 = 2,Bar4 = 2,Bar5 = 2,Bar6 = 2,Bar7 = 2}
那么值的输出2将是Bar3,甚至更糟糕的是,如果我们要在Bar1之前再添加2个值(我把值移到5,这样我们就不会与要检查的值重叠):
enum Foo {Bar0,Bar00,Bar000,Bar1 = 5,Bar2 = 5,Bar3 = 5,Bar4 = 5,Bar5 = 5,Bar6 = 5,Bar7 = 5}
然后,如果我们运行命令:
Console.WriteLine((Foo)5);
//会输出: Bar2
因此,对于在该序列之前添加的每两个标识符,它将返回一个,但是我尝试了别的方法,在序列之后又添加了两个标识符,猜猜看,它回到了Bar3,然后又添加了两个,它转到了Bar4,如果您继续添加这么多标识符,那么它应该比Bar7多,那么它将循环并显示Bar1。
我承认,这让我感到困惑,因为这意味着当给定值有多个标识符时,按值使用enum变得不可预测,特别是当不清楚时,并且在开发过程中,我们添加该enum而不知道它会影响我们,并且我们可能会依赖于这些标识符的输出。
尽管我们不会看到每个值都有两个以上标识符的情况,但仍然需要注意,因为按值使用enum并不少见,而且我的意思是,当我想到这一点时,至少有三种常见的用法,就像HTML下拉列表中有数字值一样,调用使用数字来表示某个enum值WebAPI调用,数据库持久性,就像MongoDB将使用数值来存储一个enum,并且我确信还有更多的情况使用这种机制。
幸运的是,我的一位同事想出了一个答案来避免这个问题,那就是保存或发送enum值作为文本然后解析它们,这样,我们肯定知道我们指的是正确的标识符。
PS:其实最好是设法让其值唯一即可
原文地址:
转载地址:http://rwzhj.baihongyu.com/