Оператор нуль-коалесценции - зачем кастинг?
Может кто-нибудь сказать, пожалуйста, почему первое из следующих утверждений выдает ошибку компиляции, а второе - нет?
NewDatabase.AddInParameter(NewCommand, "@SomeString", DbType.String, SomeString ?? DBNull.Value); // <-- Throws compilation error!
NewDatabase.AddInParameter(NewCommand, "@SomeString", DbType.String, (object)(SomeString) ?? DBNull.Value); // <-- Compiles!
Я пробовал другие обнуляемые типы, такие как byte?
и получил тот же результат. Может ли кто-нибудь сказать мне, почему мне нужно сначала привести объект к объекту?
5 ответов
Вы должны указать компилятору, какой тип использовать. Тип результата оператора слияния null должен совпадать с типом операнда (или базовым типом первого операнда, если в некоторых случаях это тип значения, допускающий значение NULL). Он не пытается найти "наиболее специфический тип, в который могут быть преобразованы оба операнда", или что-то подобное.
Подробнее о том, как определяется язык, когда дело доходит до оператора объединения нулей, см. Спецификацию языка C# 4, раздел 7.13:
Тип выражения
a ?? b
зависит от того, какие неявные преобразования доступны для операндов. В порядке предпочтения типa ?? b
являетсяA0
,A
, или жеB
, гдеA
это типa
(при условии, что a имеет тип),B
это типb
(при условии, чтоb
имеет тип), иA0
это основной типA
еслиA
обнуляемый тип, илиA
иначе.
Первый пример терпит неудачу, потому что SomeString
а также DBValue.Null
не являются неявно взаимозаменяемыми типами.
Это связано с тем, что тип в правой части оператора слияния нуля должен быть неявно преобразован в тип в левой части (или наоборот). Для вашего первого примера задействованы следующие типы: string
а также DBNull
, Эти типы не связаны, поэтому преобразование не выполняется.
Потому что выражение должно иметь один тип возвращаемого значения. поскольку String
а также DbValue
не может быть приведен друг к другу, компилятор не может определить, какой тип возврата вы хотите. Когда вы приводите к Object, вы предоставляете компилятору тип, на который он может привести.
DBValue.Null не является строкой; это объект..NET не будет неявно приведен к Object в выражениях; должно быть явно сказано, что вы ожидаете результата Object.