简体   繁体   中英

Why does C# 3 allow the implicit conversion of literal zero (0) to any Enum?

C#3 (Visual Studio 2008) introduced a breaking change to the language ( http://msdn.microsoft.com/en-us/library/cc713578.aspx , see change 12) that allows any literal zero to be implicitly converted to an Enum. This seems odd in many ways. Does anyone know why this is part of the spec? Why not a literal one? Or seven? Why is zero special? And it makes some very counterintuitive overload resolution choices. For instance.

function string F(object o) { return o.ToString(); }
function string F(DbType t) { return t.ToString(); }
int i = 0;
F((long)0) == "String" // would have been "0" in VS 2005
F(0) == "String"
F(i) == "0"

Very confusing, and an intentionally introduced breaking change to the language. Any ideas?

C# has always allowed the implicit conversion of the literal 0 to any Enum value. What has changed is how the rule is applied to other constant expressions. It was made to be more consistent and allow any constant expressions which evaluates to 0 to be implicitly convertible to an enum.

The example you gave produces the same behavior in all versions of C#.

Here is an example of changed behavior (directly from the linked documentation )

public enum E
{
    Zero = 0,
    One = 1,
} 

class A
{
    public static A(string s, object o)
    { System.Console.WriteLine("{0} => A(object)", s); } 

    public static A(string s, E e)
    { System.Console.WriteLine("{0} => A(Enum E)", s); }

    static void Main()
    {
        A a1 = new A("0", 0);
        A a3 = new A("(int) E.Zero", (int) E.Zero);
    }
}

Visual C# 2005 output:

\n0 => A(Enum E) \n(int) E.Zero => A(object)  

Visual C# 2008 output:

\n0 => A(Enum E) \n(int) E.Zero => A(Enum E)  

I would guess that it is because 0 is considered the "Default Value" of enums.

C# (default keyword was introduced in C# 2.0)

enum DbType {
    Unspecified,
    SqlServer
}

DbType t;
int i = 0;

Console.WriteLine(t == i);
Console.WriteLine(i == default(DbType));

Outputs:

True
True

It has been allowed since version 1.0. It is the default value of an enum.

"A literal 0 is implicitly convertible to any enum type. In Visual C# 2005 and earlier versions of the compiler, there are also some constant expressions that evaluate to 0 that can implicitly convert to any enum type, but the rule that determines which of these expressions are convertible is unclear. In Visual C# 2008, all constant expressions that are equal to 0 can be implicitly converted to any enum type."

"The default underlying type of the enumeration elements is int. By default, the first enumerator has the value 0, and the value of each successive enumerator is increased by 1." - This is from MSDN notes for 1.1 framework , so it's always been the case.

As others have mentioned, 0 is the default enum. Try to think of enumerations as follows (in a more explicit fashion):

public enum HairColor
{
    Blonde           = 0x0000;
    Brunett          = 0x0001;
    Red              = 0x0002;
    StrawberryBlonde = 0x0004;
}

Because you are not being explicit in your values of a given enumeration, C# will automagically assign it a default value. If you don't want that, then you will have to explicitely define the values for a given enumeration.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM