I’ve found very strange C# compiler behavior for following code:
var p1 = new SqlParameter("@p", Convert.ToInt32(1));
var p2 = new SqlParameter("@p", 1);
Assert.AreEqual(p1.Value, p2.Value); // PASS
var x = 0;
p1 = new SqlParameter("@p", Convert.ToInt32(x));
p2 = new SqlParameter("@p", x);
Assert.AreEqual(p1.Value, p2.Value); // PASS
p1 = new SqlParameter("@p", Convert.ToInt32(0));
p2 = new SqlParameter("@p", 0);
Assert.AreEqual(p1.Value, p2.Value); // FAIL!?
In last line assert fails with following message:
Expected: 0
But was: null
I understand why test fails: p2 = new SqlParameter("@p", 0); is resolved as SqlParameter(string, SqlDbType) and for other cases as SqlParameter(string, object). But I don’t understand why this happens. For me it looks like a bug, but I can’t believe that C# compiler could have such kind of bug.
Any reasons for this?
P.S. It seems to be a problem for any method overload with enum parameter and 0 value (SqlDbType is enum).
Basically, the decimal integer literal
0is implicitly convertible to all enum types (C# 4 spec §6.1.3), so the compiler determines thatSqlParameter(string, SqlDbType)is an applicable function member. Then it has to choose the better between two candidates function members, and it picksSqlParameter(string, SqlDbType)overSqlParameter(string, object), becauseSqlDbTypeis a more specific type thanobject(§7.5.3.2).But I agree that in that case it’s very confusing…