11

次のコードで非常に奇妙なC#コンパイラの動作を見つけました:

    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!?

最後の行で、assertは次のメッセージで失敗します。

  Expected: 0
  But was:  null

テストが失敗する理由を理解しています。他の場合はとしてp2 = new SqlParameter("@p", 0);解決されます。しかし、なぜこれが起こるのかわかりません。私にはバグのように見えますが、C#コンパイラにそのようなバグがあるとは信じられません。SqlParameter(string, SqlDbType)SqlParameter(string, object)

これには何か理由がありますか?

PS enumパラメーターと0の値(SqlDbTypeはenum)を使用したメソッドのオーバーロードでは、問題があるようです。

4

1 に答える 1

11

基本的に、10 進整数リテラル0はすべての列挙型に暗黙的に変換できるため (C# 4 仕様 §6.1.3)、コンパイラはそれSqlParameter(string, SqlDbType)が適用可能な関数メンバーであると判断します。次に、2 つの関数メンバー候補の中からより適切なものを選択する必要があり、は(§7.5.3.2)SqlParameter(string, SqlDbType)よりも具体的な型であるSqlParameter(string, object)ため、を選択します。SqlDbTypeobject

しかし、その場合、非常に混乱することに同意します...

于 2011-11-22T14:51:52.537 に答える