32

我检查了 C# 语言规范中有关枚举的部分,但无法解释以下代码的输出:

enum en {
    a = 1, b = 1, c = 1,
    d = 2, e = 2, f = 2,
    g = 3, h = 3, i = 3,
    j = 4, k = 4, l = 4
}

en[] list = new en[] {
    en.a, en.b, en.c,
    en.d, en.e, en.f,
    en.g, en.h, en.i,
    en.j, en.k, en.l
};
foreach (en ele in list) {
    Console.WriteLine("{1}: {0}", (int)ele, ele);
}

它输出:

c: 1
c: 1
c: 1
d: 2
d: 2
d: 2
g: 3
g: 3
g: 3
k: 4
k: 4
k: 4

现在,为什么它会选择第三个“1”,第一个“2”和“3”,而第二个“4”?这是未定义的行为,还是我遗漏了一些明显的东西?

4

1 回答 1

36

这被特别记录为未记录的行为。

代码的编写方式可能会导致每次都选择相同的内容,但Enum.ToString 的文档说明了这一点:

如果多个枚举成员具有相同的基础值,并且您尝试根据其基础值检索枚举成员名称的字符串表示形式,则您的代码不应对该方法将返回哪个名称做出任何假设。

(我的重点)

正如评论中提到的,不同的 .NET 运行时可能会返回不同的值,但未记录行为的整个问题在于它很容易无缘无故地发生变化(看似)。它可能会根据天气、时间、程序员的心情甚至在 .NET 运行时的修补程序中发生变化。您不能依赖无证行为

请注意,在您的示例中,ToString这正是您想要查看的内容,因为您正在打印该值,这反过来会将其转换为字符串。

如果您尝试进行比较,则具有相同基础数值的所有枚举值都是等效的,并且您无法分辨出您首先将哪个值存储在变量中。

换句话说,如果你这样做:

var x = en.a;

事后没有办法推断出你写en.a的不是en.b,或者en.c因为它们都比较相等,它们都具有相同的潜在价值。好吧,没有创建一个读取自己源代码的程序。

于 2014-07-20T16:40:48.360 回答