While using an external API that has several overloads that take different data types but no enums, I decided to create a handy method to give a bit more type-safety to enums and ended up with something like this:
namespace TestEnumPromotion
{
enum Values
{
Value0,
Value1,
}
class Program
{
static void Main(string[] args)
{
// Prints int
Overloaded(0);
// Prints Values
Overloaded(Values.Value0);
// Does not compile! :-/
Overloaded((byte) 0);
// Prints int
byte b = 0;
Overloaded(b);
}
static void Overloaded(int i)
{
Console.WriteLine("int");
}
static void Overloaded(Values i)
{
Console.WriteLine("Values");
}
}
}
But I was very surprised to see that the code does not compile because Overloaded((byte) 0)
:
The call is ambiguous between the following methods or properties: 'Program.Overloaded(int)' and 'Program.Overloaded(Values)'
But byte
cannot be automatically promoted to Values
, that is Values v = (byte)b
will not compile because:
Cannot implicitly convert type 'byte' to '`TestEnumPromotion.Values`'.
So the only possible overload should be int, right?
I thought that maybe enums were just syntactic sugar and that the compiler would generate methods that received int, but looking at the IL through ILDASM shows that a method was actually created that takes the enum.
.method private hidebysig static void Overloaded(valuetype TestEnumPromotion.Values i) cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "Values"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
} // end of method Program::Overloaded
What is happening?