I'm wrestling with a weird, at least for me, method overloading resolution of .net. I've written a small sample to reproduce the issue:
class Program
{
static void Main(string[] args)
{
var test = new OverloadTest();
test.Execute(0);
test.Execute(1);
Console.ReadLine();
}
}
public class OverloadTest
{
public void Execute(object value)
{
Console.WriteLine("object overload: {0}", value);
}
public void Execute(MyEnum value)
{
Console.WriteLine("enum overload: {0}", value);
}
}
public enum MyEnum
{
First = 1, Second = 2, Third = 3
}
Will print:
enum overload: 0
object overload: 1
Basically the overload called is different depending on the value (0, 1) instead of the given data type.
Could someone explain?
Update
I should have pointed out that there's a different behaviour between C# 2 and C# 3
Do((long)0) => object overload //C# 2
Do((long)0) => enum overload //C# 3
Yes - the constant 0 is implicitly convertible to any enum type. The constant 1 is only explicitly convertible to the enum type. Both are implicitly convertible to object
(via boxing) but the conversion to the enum is preferred where it's available.
Note that this has nothing to do with what values the enum defines. The conversion for any non-zero value is explicit whether it matches a value in the enum or not. It's just a special case for the value 0, which makes some other code simpler (particularly when dealing with flags). I don't have the spec on hand to find the reference, I'm afraid.
Bonus strangeness: due to a bug in the MS compiler (never to be fixed - it would break backward compatibility) it's actually various zero constants, not just an integer. So Execute(0d)
and Execute(0m)
will convert a double and a decimal to the enum too. It doesn't work for every zero constant - it depends on the exact nature of the source code. It's all very odd - follow the link where Eric Lippert reveals all...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With