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

时间:2014-10-12 03:18:43

标签: c# .net enums

如果我声明一个类似

的枚举
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?

这里到底发生了什么?

3 个答案:

答案 0 :(得分:3)

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

当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);

结果现在为Wen,再次更改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具有相同的时候你不应该假设这样的输出不同名称的价值......

那就是说,我认为您现在可以很容易地了解代码中发生了什么。

参考:Link

编辑:

@ GrantWinney的回答让我想到了这一点,他写道Array.BinarySearch传递了值数组和要搜索的值,所以我从名称Array.BinarySearch中意识到它是绝对使用BinarySearch并解释所有内容......

Binary Search会像这样划分数组:

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

答案 1 :(得分:3)

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

Console.WriteLine(obj);

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

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

  

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

如果两个或两个以上的值相同,它不会声明如何确定要返回的名称。

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

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

因此,您有一个包含多个1的数组,并且您正在搜索1。该调用的docs类似:

  

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

同样,它并没有说明如何进行选择,只是它不可靠。

答案 2 :(得分:2)