任何人都可以告诉我为什么以下第一个语句会抛出编译错误而第二个语句不会抛出?
NewDatabase.AddInParameter(NewCommand, "@SomeString", DbType.String, SomeString ?? DBNull.Value); // <-- Throws compilation error!
NewDatabase.AddInParameter(NewCommand, "@SomeString", DbType.String, (object)(SomeString) ?? DBNull.Value); // <-- Compiles!
我尝试了其他可以为空的类型,例如byte?
,并得到了相同的结果。任何人都可以告诉我为什么我需要先投射到对象?
答案 0 :(得分:10)
您需要告诉编译器要使用的类型。空合并运算符的结果类型必须与操作数类型的一个相同(或者在某些情况下,如果它是可空值类型,则与第一个操作数的基础类型相同)。它并不试图找到“两个操作数都可以转换为”的特定类型或类似的东西。
有关如何在空合并运算符中定义语言的详细信息,请参阅C# 4 language specification,第7.13节:
表达式
a ?? b
的类型取决于操作数上可用的隐式转换。按优先顺序排列,a ?? b
的类型为A0
,A
或B
,其中A
为a
的类型(已提供) a有类型),B
是b
的类型(假设b
有类型),A0
是A
的基础类型如果A
是可以为空的类型,则为A
。
答案 1 :(得分:9)
第一个示例失败,因为SomeString
和DBValue.Null
不是implicitly interchangable types。
答案 2 :(得分:4)
这是因为null-coalescing运算符右侧的类型必须可以隐式转换为左侧的类型(反之亦然)。对于您的第一个示例,涉及的类型为string
和DBNull
。这些类型不相关,因此转换失败。
答案 3 :(得分:2)
DBValue.Null不是字符串;它是一个对象。 .NET不会在表达式中隐式地转换为Object;必须明确告诉你,你期待一个Object结果。
答案 4 :(得分:2)
因为表达式需要有一个返回类型。由于String
和DbValue
无法相互转换,因此编译器无法确定您想要哪种类型的返回。当你转换为Object时,你给编译器一个它可以强制转换的类型。