c# —— 枚举和值的隐藏副作用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mzl87/article/details/84978914

最近,我遇到了enum的问题,我想分享一下,以防其他人遇到它。

enum是什么?

Enums是一个数值常量列表,可以帮助我们处理许多情况,例如某些东西可以有标记或属性,以区别于另一个对象,或者它们代表方法的不同选项。其他时候,它们代表一个对象或关系的状态,例如,我们可以使用Employee enum告诉我们一个人是经理,副总裁,CEO

但无论我们给enum什么名称,在后台,它只是一个用于代表该状态的数字,如下所示:

enum Foo {
Bar1,
Bar2,
Bar3,
}

因此,在本例中,我们声明了一个名为Fooenum,它可以具有3个值之一,Bar1,隐式地具有0Bar2,其值为1Bar3具有值2

问题在于enum的背景值以及我们如何使用它,例如,因为我们知道Bar2的值为1,我们可以将数字1转换为Foo类型的枚举,我们将得到如下的Bar2

Console.WriteLine((Foo)1);

//会输出: Bar2

但是既然我们在谈论数字,那么enums也可以映射到这样的特定值:

enum Foo {
Bar1 = 2,
Bar2,
Bar3 = 5,
}

基本上,在这种情况下,Bar1将有一个值2, Bar2将具有值3Bar3并将具有值5

而现在是奇怪的部分和副作用。

我们可以用enum为同一个值定义两个或多个标识符,如下所示:

enum Foo {
Bar1 = 2,
Bar2 = 2,
Bar3,
}

请注意,Bar1Bar2具有相同的值(不一定是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下拉列表中有数字值一样,调用使用数字来表示某个enumWebAPI调用,数据库持久性,就像MongoDB将使用数值来存储一个enum,并且我确信还有更多的情况使用这种机制。

幸运的是,我的一位同事想出了一个答案来避免这个问题,那就是保存或发送enum值作为文本然后解析它们,这样,我们肯定知道我们指的是正确的标识符。

PS:其实最好是设法让其值唯一即可

原文地址:https://www.codeproject.com/Articles/1266988/The-Hidden-Side-effect-of-Enums-and-Values

猜你喜欢

转载自blog.csdn.net/mzl87/article/details/84978914
今日推荐