我看了this question,发现Tim Schmelter's answer:
顺便说一句,这是条件运算符和if-else
之间的差异之一
你可以查看这个问题的答案,我找不到原因吗?
如果条件运算符像if-else那样工作,为什么if else不需要强制转换
问题:
int? l = lc.HasValue ? (int)lc.Value : null;
“Tim Schmelter”回答:
您还必须投射null
:
int? l = lc.HasValue ? (int)lc.Value : (int?)null;
顺便说一句,这是conditional operator和if-else
之间的差异之一:
if (lc.HasValue)
l = (int)lc.Value;
else
l = null; // works
答案 0 :(得分:5)
单独的文字null
没有类型,但它可以隐式转换为任何引用类型和任何Nullable<>
类型。在表达式中:
x = null
其中x
被赋值为null,编译器可以很容易地从变量的类型(或字段或属性或参数或其他)x
推断null
字面值应该是什么转换成。例如,如果x
属于string
类型,则null
应代表null
引用,而如果x
属于int?
类型,则null
代表Nullable<int>
HasValue
为假的实例。
如果x
的类型为int
,则不存在隐式转换,并且上述表达式不会编译。
(声明var x = null;
与var
不合法,因为null
本身没有类型。)
另一方面,在表达式中:
someBoolean ? 42 : null /* illegal */
编译器无法确定将null
转换为什么类型。请注意,int
既不是引用类型,也不是Nullable<>
类型。
如果您将包装表示为可空,请使用:
someBoolean ? (int?)42 : null
或:
someBoolean ? 42 : (int?)null
在这两种情况下,编译器都会自动看到另一个操作数(在冒号:
的另一侧)也必须隐式转换为int?
。
如果您将装箱指代int
的某个基类或接口,请写下:
someBoolean ? (object)42 : null
或:
someBoolean ? 42 : (object)null
现在,上面的表达式可能是包含更大表达式的子表达式,但编译器仍然需要?:
表达式的类型才能自行清除。例如:
int? x;
x = someBoolean ? 42 : null; // still illegal!
即使子表达式someBoolean ? 42 : null
出现在较大的表达式x = someBoolean ? 42 : null
中,其中x
确实具有类型,但子表达式仍必须“内在地”获取其类型。 x
的类型不能“泄漏”子表达式。对于许多新的C#开发人员来说,这种“语法”似乎是一个惊喜。像你这样的问题经常出现,例如, Nullable type issue with ?:
Conditional Operator以及与之关联的主题。
答案 1 :(得分:1)
if
语句不会产生值,因此“then”和“else”部分中的语句不需要以任何方式兼容。
条件运算符产生一个值,因此两个部分必须以某种方式兼容,以便编译器确定表达式的类型。
答案 2 :(得分:0)
MSDN对条件运算符说:
* first_expression和second_expression的类型必须相同,或者从一种类型到另一种类型必须存在隐式转换。*
这就是原因。在 if-else 构造函数中, else 块中的代码独立于 if 块中的代码,因此类型转换可以由每种情况都有编译器。