空聚焦运算符-为什么铸造
本文关键字:为什么 聚焦 运算符 | 更新日期: 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
的类型是A0
、A
或B
,其中A
是a
的类型(前提是a具有类型),B
是b
的类型(条件是b
具有类型);如果A
是可为null的类型,则A0
是A
的底层类型,否则为A
。
第一个示例失败,因为SomeString
和DBValue.Null
不是可隐式交换的类型。
这是因为null合并运算符右侧的类型必须隐式转换为左侧的类型(反之亦然)。对于第一个示例,所涉及的类型是string
和DBNull
。这些类型是不相关的,因此转换失败。
DBValue.Null不是字符串;它是一个对象。NET不会在表达式中隐式转换为Object;必须明确地告诉它您正在期待一个Object结果。
因为表达式需要有一个返回类型。由于String
和DbValue
不能相互转换,编译器无法确定您想要哪种类型的返回。当您转换为Object时,您为编译器提供了一个可以转换为的类型。