首先,有一点背景。阅读问题并接受答案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)
当编译器执行重载解决方案时,对于
SqlDbType
和object
构造函数,0均为Applicable function member,因为:(
SqlDbType x = 0
和object x = 0
均有效)SqlDbType
参数优于object
参数,因为better conversion rules:T1
和T2
是相同的类型,则两种转换都不会更好。object
和SqlDbType
不是同一类型S
是T1
,则C1
是更好的转换。0
不是object
S
是T2
,则C2
是更好的转换。0
不是SqlDbType
T1
到T2
的隐式转换,并且不存在从T2
到T1
的隐式转换,则C1
是更好的转换。object
到SqlDbType
的隐式转换T2
到T1
的隐式转换,并且不存在从T1
到T2
的隐式转换,则C2
是更好的转换。SqlDbType
到object
的隐式转换,因此SqlDbType
是更好的转换请注意,确切构成常数0的内容在Visual C# 2008(微软对C#规范的实现)中(相当巧妙地)发生了变化,正如@Eric在其回答中解释的那样。