2011-06-13 42 views
4

任何人都可以请告诉我为什么下面的第一个语句会引发编译错误,第二个语句不会呢?空煤炭操作员 - 为什么要铸造?

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

究竟是编译错误? NewDatabase.AddInParameter的签名是什么? – Vlad 2011-06-13 16:23:12

+1

签名是'void AddInParameter(DbCommand,string,DBType,object)'。编译错误是“运营商”??不能应用于'string'和'System.DBNull'类型的操作数“。 – 2011-06-13 16:24:11

+0

相关问题 - http://stackoverflow.com/questions/13698421/is-if-condition-better-than-and-casting – Lijo 2012-12-04 16:57:21

回答

10

您需要告诉编译器使用哪种类型。空合并运算符的结果类型必须与操作数类型的一个一个相同(或者在某些情况下,如果它是可为空的值类型,则为第一个操作数的基础类型)。它并没有试图找到“两种操作数都可以转换成的最具体类型”或类似的东西。

有关的语言是如何当它涉及到的空合并运算符规定的详情,请参阅C# 4 language specification,部分7.13:

类型表达a ?? b取决于其隐式转换都可以在操作数。按优先顺序,的a ?? b类型是A0A,或B,其中Aa类型(条件是a具有类型),Bb类型(前提是b具有类型),和A0A的基本类型,如果A是可以为空的类型,则为A,否则为A

4

这是因为null-coalescing操作符右侧的类型必须隐式转换为左侧的类型(反之亦然)。对于你的第一个例子,涉及的类型是stringDBNull。这些类型无关,所以转换失败。

+0

转换也可以反过来 - 从左到右。 – 2011-06-13 16:28:09

2

DBValue.Null不是字符串;这是一个对象。 .NET不会在表达式中隐式转换为Object;必须明确告诉你期望得到一个Object结果。

2

因为表达式需要一个返回类型。由于StringDbValue不能互相转换,因此编译器无法确定您想要哪种类型的返回。当您投射到Object时,您将为编译器提供可投射到的类型。