使用具有相同底层类型值的条目的枚举
如果我宣布一个枚举像
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
。