6

if i declare an enum like

enum Weekdays
{
    Mon = 1,
    Tue = 1,
    Wen = 1,
    Thi,
    Fri,
    Sat,
    Sun
}

Weekdays obj = (Weekdays)1;
Console.WriteLine(obj);//Prints Tue why?

now if i change Weekdays and do the same operation as follows

enum Weekdays
{
    Mon = 1,
    Tue = 1,
    Wen = 1,
    Thi = 1,
    Fri,
    Sat,
    Sun
}

Weekdays obj = (Weekdays)1;
Console.WriteLine(obj);//Prints Thi !!!!!How?

What is really happening here?

0

3 Answers 3

9

When you write out your value like this, it ends up getting ToString() called on it.

Console.WriteLine(obj);

If you dig into the code far enough down, it's calling Enum.GetName() on your value.

Regarding multiple enum values with the same underlying value, the Enum.GetName page on MSDN says:

If multiple enumeration members have the same underlying value, the GetName method guarantees that it will return the name of one of those enumeration members. However, it does not guarantee that it will always return the name of the same enumeration member. As a result, when multiple enumeration members have the same value, your application code should never depend on the method returning a particular member's name.

It doesn't state how it determines which name to return if the values on two or more are the same.

The docs for Enum.ToString() include the same warning, in slightly different wording.

Digging a little deeper, the method above makes a call to Array.BinarySearch, passing it an array of numbers representing all values in your enum, and a number representing the value you want to print.

So you have an array with multiple 1's in it, and you're searching for a 1. The docs for that call are similar:

Duplicate elements are allowed. If the Array contains more than one element equal to value, the method returns the index of only one of the occurrences, and not necessarily the first one.

Again, it doesn't state how a selection is made, just that it'll be unreliable.

Sign up to request clarification or add additional context in comments.

3 Comments

Hey can you please read my answer and tell me if it makes sense?
@grant winney :: actually what works here ToString() or Enum.GetName() ?
I believe the reason you get the response is because of the hash codes of the various values: Mon=77548, Tue=84452, Wen=86848, Thi=84053. If you just have Mon, Tue, and Wen = 1, then the binary search lands on Tue (it's in the middle), but if you add Thi = 1 so you have 4 items, then the binary search will land on the second element, which would be Thi.
5

When you assign similar values, the result will be unexpected but I think it will evaluate for two cases:

When n is even:

(n/2)

When n is odd:

(n/2)+1

If I change the enum like this:

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

The result will be Fri, Now lets change the enum again:

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

The result is now Thi, Again change the 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);

The result is now Thi, Again change the 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);

The result is now Wen, Again change the 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);

The result is now Wen, Changing the enum again:

enum Weekdays {Mon=1,Tue=1,Wen=1,Thi=1}
// n is even = 4
// (n/2) = 2

Weekdays obj = (Weekdays)1;
Console.WriteLine(obj);

The result is now Tue, Changing the enum again:

enum Weekdays {Mon=1,Tue=1,Wen=1}
// n is odd = 3
// (n/2)+1 = 2

Weekdays obj = (Weekdays)1;
Console.WriteLine(obj);

The result is now Tue.

Even though this is explaining the behavior perfectly but this may not always happen or may not happen since I have not checked this for more cases but as MSDN says you should not assume about such output when the enum have same values for different names...

That said, I think you can easily understand now what is happening in your code.

Ref.: Link

Edit:

@GrantWinney's answer led me to this, He has written that Array.BinarySearch is passed the array of values and the value to search for so I realized from the name Array.BinarySearch that it is definitely using a BinarySearch and that explains everything...

Binary Search will divide the array like this:

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

and then Check for

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

So this explains it how the enum values are printed if their are multiple names for the value you are trying to print.

Your Original Question

enum Weekdays
{
    Mon = 1,
    Tue = 1,
    Wen = 1,
    Thi,
    Fri,
    Sat,
    Sun
}

Weekdays obj = (Weekdays)1;
Console.WriteLine(obj);//Prints Tue why?

It prints Tue because a call to Array.BinarySearch will be made passing the array

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

and a value to search which is 1...

So the BinarySearch will do this:

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

After moving left again the Mid will be calculated:

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`

The 2nd example in your Question:

enum Weekdays
{
    Mon = 1,
    Tue = 1,
    Wen = 1,
    Thi = 1,
    Fri,
    Sat,
    Sun
}

Weekdays obj = (Weekdays)1;
Console.WriteLine(obj);//Prints Thi !!!!!How?

As I have written above a call to Array.BinarySearch will be made and array:

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

will be passed with value = 1 to search...

Apply the BinarySearch algorithm on the array and it will evaluate to Thi.

5 Comments

:in your enum all constants have same value if my enum is like enum WeekDays {Mon=1,Tue=1,Wen,Thi,Fri=1,sat,Sun }; WeekDays obj = (WeekDays)1; Console.WriteLine(obj);//prints fri Can you tell me why?
Yes I changed it because I was trying to explain what happens when you have same values for different names in an enum.
@ShamseerKSmr I can not yet, But I have written that there is a pattern in my answer but that can not be 100% since it is written on MSDN that the output will be unexpected when the enum has same values for different names...
Don't know how constructive it is to try to reverse-engineer how .Net does this. The implementation may be different in different versions of .Net, and Microsoft may change the implementation in future versions. Then there's Mono, and (hopefully) other C# implementations coming in the future, each of which may do it differently.
@SyedFarjadZiaZaidi : Now you are saying that enum definitely using a BinarySearch and that explains everything... .if so my enum is like this enum WeekDays { Mon=1, Tue=1, Wen, Thi, Fri=1, sat, Sun } now try the following code WeekDays obj = (WeekDays)1; Console.WriteLine(obj);//print fri can you explaian why? as per your explanation it must print Tue but it's not.
3

As Per MSDN If multiple enumeration members have the same underlying value and you attempt to retrieve the string representation of an enumeration member's name based on its underlying value, your code should not make any assumptions about which name the method will return.

2 Comments

It happens that if you have 3 or 4 days linked to the same number:1, you get a random day among the 3 or the 4 and it is unpredictable. Why do you want 3 or 4 days with the same number?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.