首先,有一点背景。阅读问题并接受答案posted here,以获取针对我的问题的特定方案。我不确定是否存在其他类似情况,但这是我所知道的唯一情况。

上面的“怪癖”是我很长一段时间都已经意识到的事情。直到最近,我才了解起因。

微软在SqlParameter类上的文档更加清楚了这种情况。



(添加了Emph。)

我的问题是,为什么编译器会假定在您指定硬编码“0”(并且仅值为“0”)时尝试指定枚举类型,而不是整数类型?在这种情况下,假定您声明的是SqlDbType值,而不是值0。

这是不直观的,更糟糕​​的是,该错误是不一致的。我有一些以前编写的应用程序,这些应用程序已调用存储过程多年。我将对应用程序进行更改(通常甚至不与我的SQL Server类相关联),发布更新,此问题将突然中断应用程序。

当包含多个方法签名的对象包含两个相似的签名,其中一个参数是对象/整数,而另一个参数接受枚举时,为什么编译器会混淆值为0?

如前所述,我从来没有将其视为任何其他类上的任何其他构造函数或方法的问题。这是SqlParameter类所独有的,还是C#/。Net中的错误继承?

最佳答案

这是因为零整数可以隐式转换为枚举:

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)

(改自Visual C# 2008 Breaking Changes - change 12)

当编译器执行重载解决方案时,对于SqlDbTypeobject构造函数,0均为Applicable function member,因为:



(SqlDbType x = 0object x = 0均有效)
SqlDbType参数优于object参数,因为better conversion rules:
  • 如果T1T2是相同的类型,则两种转换都不会更好。
  • objectSqlDbType不是同一类型
  • 如果ST1,则C1是更好的转换。
  • 0不是object
  • 如果ST2,则C2是更好的转换。
  • 0不是SqlDbType
  • 如果存在从T1T2的隐式转换,并且不存在从T2T1的隐式转换,则C1是更好的转换。
  • 不存在从objectSqlDbType的隐式转换
  • 如果存在从T2T1的隐式转换,并且不存在从T1T2的隐式转换,则C2是更好的转换。
  • 存在从SqlDbTypeobject的隐式转换,因此SqlDbType是更好的转换

  • 请注意,确切构成常数0的内容在Visual C# 2008(微软对C#规范的实现)中(相当巧妙地)发生了变化,正如@Eric在其回答中解释的那样。

    07-24 09:44