使用具有相同底层类型值的条目的枚举

如果我宣布一个枚举像

enum Weekdays { Mon = 1, Tue = 1, Wen = 1, Thi, Fri, Sat, Sun } Weekdays obj = (Weekdays)1; Console.WriteLine(obj);//Prints Tue why? 

现在如果我改变工作日并做同样的操作如下

 enum Weekdays { Mon = 1, Tue = 1, Wen = 1, Thi = 1, Fri, Sat, Sun } Weekdays obj = (Weekdays)1; Console.WriteLine(obj);//Prints Thi !!!!!How? 

这里真的发生了什么?

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

当你像这样写出你的值时,最终会调用ToString()

 Console.WriteLine(obj); 

如果你深入挖掘代码,它会在你的值上调用Enum.GetName()

关于具有相同基础值的多个枚举值, MSDN上的Enum.GetName页面说:

如果多个枚举成员具有相同的基础值,则GetName方法保证它将返回其中一个枚举成员的名称。 但是,它不保证它始终返回相同枚举成员的名称。 因此,当多个枚举成员具有相同的值时,应用程序代码永远不应该依赖于返回特定成员名称的方法。

如果两个或多个上的值相同,则不会说明如何确定要返回的名称。

Enum.ToString()的文档包含相同的警告,措辞略有不同。

深入挖掘,上面的方法调用Array.BinarySearch ,传递一个表示枚举中所有值的数字数组,以及一个表示要打印的值的数字。

所以你有一个包含多个1的数组,而你正在搜索1 。 该调用的文档类似:

允许重复元素。 如果Array包含多个等于value的元素,则该方法仅返回其中一个出现的索引,而不一定返回第一个出现的索引。

同样,它没有说明如何做出选择,只是说它不可靠。

当您指定相似的值时,结果将是意外的,但我认为它将评估两种情况:

当n是偶数时:

 (n/2) 

当n为奇数时:

 (n/2)+1 

如果我像这样更改enum

 enum Weekdays {Mon=1,Tue=1,Wen=1,Thi=1,Fri=1,Sat=1, Sun=1, Mon2=1, Mon3=1} // n is odd = 9 // (n/2)+1 = 5 Weekdays obj = (Weekdays)1; Console.WriteLine(obj); 

结果将是Fri ,现在让我们再次更改enum

 enum Weekdays {Mon=1,Tue=1,Wen=1,Thi=1,Fri=1,Sat=1, Sun=1,Mon2=1} // n is even = 8 // (n/2) = 4 Weekdays obj = (Weekdays)1; Console.WriteLine(obj); 

结果是现在Thi ,再次改变enum

 enum Weekdays {Mon=1,Tue=1,Wen=1,Thi=1,Fri=1,Sat=1, Sun=1} // n is odd = 7 // (n/2)+1 = 4 Weekdays obj = (Weekdays)1; Console.WriteLine(obj); 

结果是现在Thi ,再次改变enum

 enum Weekdays {Mon=1,Tue=1,Wen=1,Thi=1,Fri=1,Sat=1} // n is even = 6 // (n/2) = 3 Weekdays obj = (Weekdays)1; Console.WriteLine(obj); 

结果现在是Wen ,再次改变enum

 enum Weekdays {Mon=1,Tue=1,Wen=1,Thi=1,Fri=1} // n is odd = 5 // (n/2)+1 = 3 Weekdays obj = (Weekdays)1; Console.WriteLine(obj); 

结果是现在,再次改变enum

 enum Weekdays {Mon=1,Tue=1,Wen=1,Thi=1} // n is even = 4 // (n/2) = 2 Weekdays obj = (Weekdays)1; Console.WriteLine(obj); 

结果是现在Tue ,再次更改enum

 enum Weekdays {Mon=1,Tue=1,Wen=1} // n is odd = 3 // (n/2)+1 = 2 Weekdays obj = (Weekdays)1; Console.WriteLine(obj); 

结果是现在Tue

即使这完全解释了这种行为,但这可能并不总是发生或者可能不会发生,因为我没有检查过更多的情况,但是当MSDN说你不应该假设这样的输出,当enum具有不同名称的相同值时…

也就是说,我认为您现在可以轻松了解代码中发生的情况。

参考: 链接

编辑:

@ GrantWinney的回答让我想到了这一点,他写道, Array.BinarySearch传递了值数组和值来搜索,所以我从名称Array.BinarySearch意识到它肯定是在使用BinarySearch并解释了一切……

二进制搜索将像这样划分数组:

 Mid = {Low(which is the starting index) + High (which is the last index of array)}/2 

然后检查

 if (Mid == value) return index; else if the value is smaller or equal move left other wise move right of the array 

因此,这解释了如果enum值是您要尝试打印的值的多个名称,它们是如何打印的。

你的原始问题

 enum Weekdays { Mon = 1, Tue = 1, Wen = 1, Thi, Fri, Sat, Sun } Weekdays obj = (Weekdays)1; Console.WriteLine(obj);//Prints Tue why? 

它打印Tue因为将调用Array.BinarySearch传递数组

 {1, 1, 1, 2, 3, 4, 5} 

和一个搜索的值是1

所以BinarySearch会这样做:

 Mid = {Low(0) + High(6)} / 2 if (Mid == value) return index else move left 

再次向左移动后, Mid将被计算:

 High = Mid - 1; // now only the left sub-array will be searched Mid = {Low(0) + High(2)} / 2 if (Mid == value) return index // here the condition will be true and you will be returned with `Tue` 

你问题中的第二个例子:

 enum Weekdays { Mon = 1, Tue = 1, Wen = 1, Thi = 1, Fri, Sat, Sun } Weekdays obj = (Weekdays)1; Console.WriteLine(obj);//Prints Thi !!!!!How? 

正如我上面写的那样,将调用Array.BinarySearch和数组:

 {1, 1, 1, 1, 2, 3, 4} 

将以值= 1传递给搜索…

在数组上应用BinarySearch算法,它将评估为Thi