Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wrong enum value in C# [duplicate]

Tags:

c#

enums

Why is the following printing EOF as the output and not ILLEGAL? If I remove the initialization for EOF to NULL character, it works as expected. Can't understand what is happening here?

public enum TokenType {
            ILLEGAL,
            EOF= '\0',//remove the initialization to have it work as expected
            IDENT,
            INT
            };

void Main()
{
    Console.WriteLine(TokenType.ILLEGAL);//Prints EOF. Should have printed ILLEGAL
}
like image 340
umbersar Avatar asked Dec 23 '22 16:12

umbersar


2 Answers

By initializing the EOF value with '\0' you give it a value of 0.

You can see this in this example:

Console.WriteLine(Convert.ToInt16(TokenType.EOF));
Console.WriteLine($"IntValue: {Convert.ToInt16('\0')}");

0
IntValue: 0

Internally the enum will get values starting from 0 on counting upwards in integers. So below the surface your enum looks like this:

public enum TokenType
{
    ILLEGAL = 0,
    EOF = 1
    IDENT = 2,
    INT = 3
};

But you chose to enforce a 0 on the value EOF! So you have 2 enum names representing the same value. The compiler simply takes the first one that it can find.

like image 77
Mong Zhu Avatar answered Jan 05 '23 20:01

Mong Zhu


First, note that = '\0' is the same as = 0. This is because'\0' has the numerical value of 0. Your enum has the default underlying type of int. The constant expression '\0' is converted to the int of 0 at compile time.

Second, as per the language spec, note that enum members can have duplicated associated values.

Third, from the the same section of the language spec,

The associated value of an enum member is assigned either implicitly or explicitly. [...] If the declaration of the enum member has no initializer, its associated value is set implicitly, as follows:

  • If the enum member is the first enum member declared in the enum type, its associated value is zero.

  • Otherwise, the associated value of the enum member is obtained by increasing the associated value of the textually preceding enum member by one. This increased value must be within the range of values that can be represented by the underlying type, otherwise a compile-time error occurs.

So if I were to write out your enum's members' associated values explicitly, it would be:

public enum TokenType {
        ILLEGAL = 0,
        EOF = 0,
        IDENT = 1,
        INT = 2
        };

ILLEGAL and EOF have the same associated value.

Fourth, Console.WriteLine calls ToString on your enum. Now look at what Enum.ToString does (in the Notes to Callers section):

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.

So, it outputting ILLEGAL is completely normal, as you "should not make any assumptions about which name the method will return".

like image 44
Sweeper Avatar answered Jan 05 '23 21:01

Sweeper