enum type with floating-point underlying type RRS feed

  • General discussion

  • I am surprised that the following code passes PEVerify (Version 4.0.30319.1) and runs OK, outputting True and 0. This enum definition violates ECMA-335 6th ed. §II.14.3.

    .class private auto ansi sealed EnumFloat.EFlo
           extends [mscorlib]System.Enum
      .field public specialname rtspecialname float32 value__
      .field public static literal valuetype EnumFloat.EFlo GG = float32(24.25)
    } // end of class EnumFloat.EFlo
    .class private abstract auto ansi sealed beforefieldinit EnumFloat.Program
           extends [mscorlib]System.Object
      .method private hidebysig static void  Main(string[] args) cil managed
        .maxstack  8
        .locals init (
            [0] valuetype EnumFloat.EFlo f,
            [1] class [mscorlib]System.Enum e)
        ldc.r4     24.25
        box        EnumFloat.EFlo
        callvirt   instance bool [mscorlib]System.Object::Equals(object)
        call       void [mscorlib]System.Console::WriteLine(bool)
        call       instance int32 [mscorlib]System.Enum::CompareTo(object)
        call       void [mscorlib]System.Console::WriteLine(int32)
      } // end of method Program::Main
    } // end of class EnumFloat.Program

    In the CoreCLR source, the underlying type of the enum is validated in by RegMeta::ValidateTypeDef, which explicitly allows ELEMENT_TYPE_R4 and ELEMENT_TYPE_R8. So does ReflectionEnum::InternalCompareTo, which is used in Enum.CompareTo.

    Enum.ToString however does not work:

    Unhandled Exception: System.ArgumentException: The value passed in must be an en
    um base or an underlying type for an enum, such as an Int32.
    Parameter name: value
       at System.RuntimeType.GetEnumName(Object value)
       at System.Enum.GetName(Type enumType, Object value)
       at System.Enum.InternalFormat(RuntimeType eT, Object value)
       at System.Enum.ToString()
       at System.Enum.ToString(String format)
       at System.Enum.ToString(String format, IFormatProvider provider)
       at System.IO.TextWriter.WriteLine(Object value)
       at System.IO.TextWriter.SyncTextWriter.WriteLine(Object value)
       at EnumFloat.Program.Main(String[] args)
    Tuesday, January 17, 2017 9:33 PM