It’s because a zero-integer is implicitly convertible to an enum:
enum SqlDbType
{
Zero = 0,
One = 1
}
class TestClass
{
public TestClass(string s, object o)
{ System.Console.WriteLine("{0} => TestClass(object)", s); }
public TestClass(string s, SqlDbType e)
{ System.Console.WriteLine("{0} => TestClass(Enum SqlDbType)", s); }
}
// This is perfectly valid:
SqlDbType valid = 0;
// Whilst this is not:
SqlDbType ohNoYouDont = 1;
var a1 = new TestClass("0", 0);
// 0 => TestClass(Enum SqlDbType)
var a2 = new TestClass("1", 1);
// => 1 => TestClass(object)
(Adapted from Visual C# 2008 Breaking Changes – change 12)
When the compiler performs the overload resolution 0 is an Applicable function member for both the SqlDbType
and the object
constructors because:
an implicit conversion (Section 6.1) exists from the type of the argument to the type of the corresponding parameter
(Both SqlDbType x = 0
and object x = 0
are valid)
The SqlDbType
parameter is better than the object
parameter because of the better conversion rules:
- If
T1
andT2
are the same type, neither conversion is better.object
andSqlDbType
are not the same type
- If
S
isT1
,C1
is the better conversion.0
is not anobject
- If
S
isT2
,C2
is the better conversion.0
is not aSqlDbType
- If an implicit conversion from
T1
toT2
exists, and no implicit conversion fromT2
toT1
exists,C1
is the better conversion.- No implicit conversion from
object
toSqlDbType
exists
- No implicit conversion from
- If an implicit conversion from
T2
toT1
exists, and no implicit conversion fromT1
toT2
exists,C2
is the better conversion.- An implicit conversion from
SqlDbType
toobject
exists, so theSqlDbType
is the better conversion
- An implicit conversion from
Note that what exactly constitutes a constant 0 has (quite subtly) changed in Visual C# 2008 (Microsoft’s implementation of the C# spec) as @Eric explains in his answer.