空聚焦运算符-为什么铸造

本文关键字:为什么 聚焦 运算符 | 更新日期: 2023-09-27 17:58:57

有人能告诉我为什么下面的第一条语句会引发编译错误,而第二条则不会?

NewDatabase.AddInParameter(NewCommand, "@SomeString", DbType.String, SomeString ?? DBNull.Value); // <-- Throws compilation error!
NewDatabase.AddInParameter(NewCommand, "@SomeString", DbType.String, (object)(SomeString) ?? DBNull.Value); // <-- Compiles!

我尝试了其他可以为null的类型,如byte?,得到了相同的结果。有人能告诉我为什么我需要先投反对票吗?

空聚焦运算符-为什么铸造

您需要告诉编译器要使用什么类型。null合并运算符的结果类型必须与一个操作数类型相同(在某些情况下,如果是可为null的值类型,则为第一个操作数的基础类型)。它不试图找到"两个操作数都可以转换为的最特定类型"或类似的类型。

有关在空合并运算符中如何定义语言的详细信息,请参阅C#4语言规范第7.13节:

表达式a ?? b的类型取决于哪些隐式转换可用于操作数。按照偏好的顺序,a ?? b的类型是A0AB,其中Aa的类型(前提是a具有类型),Bb的类型(条件是b具有类型);如果A是可为null的类型,则A0A的底层类型,否则为A

第一个示例失败,因为SomeStringDBValue.Null不是可隐式交换的类型。

这是因为null合并运算符右侧的类型必须隐式转换为左侧的类型(反之亦然)。对于第一个示例,所涉及的类型是stringDBNull。这些类型是不相关的,因此转换失败。

DBValue.Null不是字符串;它是一个对象。NET不会在表达式中隐式转换为Object;必须明确地告诉它您正在期待一个Object结果。

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