Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange C# compiler behavior (overload resolution)

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).

like image 669
Victor Haydin Avatar asked Nov 22 '11 14:11

Victor Haydin


1 Answers

Basically, the decimal integer literal 0 is implicitly convertible to all enum types (C# 4 spec §6.1.3), so the compiler determines that SqlParameter(string, SqlDbType) is an applicable function member. Then it has to choose the better between two candidates function members, and it picks SqlParameter(string, SqlDbType) over SqlParameter(string, object), because SqlDbType is a more specific type than object (§7.5.3.2).

But I agree that in that case it's very confusing...

like image 54
Thomas Levesque Avatar answered Oct 26 '22 07:10

Thomas Levesque