How is it that an enum derives from System.Enum and is an integer at the same time?

后端 未结 8 793
刺人心
刺人心 2021-01-30 16:51

Edit: Comments at bottom. Also, this.


Here\'s what\'s kind of confusing me. My understanding is that if I have an enum like this...



        
8条回答
  •  醉梦人生
    2021-01-30 17:12

    What I'm noting here is from page 38 of ECMA-335 (I suggest you download it just to have it):

    The CTS supports an enum (also known as an enumeration type), an alternate name for an existing type. For the purposes of matching signatures, an enum shall not be the same as the underlying type. Instances of an enum, however, shall be assignable-to the underlying type, and vice versa. That is, no cast (see §8.3.3) or coercion (see §8.3.2) is required to convert from the enum to the underlying type, nor are they required from the underlying type to the enum. An enum is considerably more restricted than a true type, as follows:

    The underlying type shall be a built-in integer type. Enums shall derive from System.Enum, hence they are value types. Like all value types, they shall be sealed (see §8.9.9).

    enum Foo { Bar = 1 }
    Foo x = Foo.Bar;
    

    This statement will be false because of the second sentence:

    x is int
    

    They are the same (an alias), but their signature is not the same. Converting to and from an int isn't a cast.

    From page 46:

    underlying types – in the CTS enumerations are alternate names for existing types (§8.5.2), termed their underlying type. Except for signature matching (§8.5.2) enumerations are treated as their underlying type. This subset is the set of storage types with the enumerations removed.

    Go back to my Foo enum earlier. This statement will work:

    Foo x = (Foo)5;
    

    If you inspect the generated IL code of my Main method in Reflector:

    .method private hidebysig static void Main(string[] args) cil managed
    {
    .entrypoint
    .maxstack 1
    .locals init (
        [0] valuetype ConsoleTesting.Foo x)
    L_0000: nop 
    L_0001: ldc.i4.5 
    L_0002: stloc.0 
    L_0003: call string [mscorlib]System.Console::ReadLine()
    L_0008: pop 
    L_0009: ret 
    }
    

    Note there's no cast. ldc is found on page 86. It loads a constant. i4 is found on page 151, indicating the type is a 32-bit integer. There isn't a cast!

提交回复
热议问题