为什么在三元运算符中赋值null失败:null和int之间没有隐式转换?

Zac*_*ott 11 c# ternary-operator

这失败了 There is no implicit conversion between 'null' and 'int'

long? myVar = Int64.Parse( myOtherVar) == 0 ? null : Int64.Parse( myOtherVar);
Run Code Online (Sandbox Code Playgroud)

但是,这成功了:

if( Int64.Parse( myOtherVar) == 0)
    myVar = null;
else
    myVar = Int64.Parse( myOtherVar);
Run Code Online (Sandbox Code Playgroud)

有没有办法让三元运算符成功?

jas*_*son 25

在确定右侧的类型时,编译器会忽略左侧.所以当它试图推断出类型时

Int64.Parse(myOtherVar) == 0 ? null : Int64.Parse(myOtherVar)
Run Code Online (Sandbox Code Playgroud)

它没有注意到左手边是一个事实long?.为了确定右侧的类型,它注意到了这一点

Int64.Parse(myOtherVar)
Run Code Online (Sandbox Code Playgroud)

是一个long,现在试图看是否null或可以隐式转换为long.由于它不能,您会收到您看到的错误消息.

从C#规范的§7.14开始:

形式的条件表达式b ? x : y....

在第二和第三操作数,x并且y,所述的?:操作者控制所述条件表达式的类型.

(1)如果x有类型X并且y有类型Y那么

一个.如果一个隐式转换(第6.1节)从存在XY,但不能从YX,然后Y是条件表达式的类型.

湾 如果一个隐式转换(第6.1节)从存在YX,但不能从XY,然后X是条件表达式的类型.

C.否则,无法确定表达式类型,并发生编译时错误.

(2)如果只有一个的xy有一个类型,并且两个xy,areimplicitly转换为这种类型的,那么这就是条件表达式的类型.

(3)否则,不能确定表达式类型,并发生编译时错误.

请注意,我们是在情况(2)其中xnull,没有一个类型,yInt64.Parse(myOtherVar)和有型long.注意,x不能隐式转换为类型y.因此,(1)和(2)都失败了,我们导致(3)导致编译时错误激发了你的问题.请注意上面的隐含结论,即左侧在确定右侧的类型时不起作用.

纠正这个替换

Int64.Parse(myOtherVar)
Run Code Online (Sandbox Code Playgroud)

(long?)Int64.Parse(myOtherVar)
Run Code Online (Sandbox Code Playgroud)

现在,之所以如此

myVar = null;
Run Code Online (Sandbox Code Playgroud)

还好这里myVar被宣布为long?是因为编译器知道有一个隐含的转换,从nulllong?.

最后,Int64.Parse如果myOtherVar无法解析将抛出long.请注意,您还要执行两次解析,这是不必要的.一个更好的模式是

long value;
if(Int64.TryParse(myOtherVar, out value)) {
    myVar = value == 0 ? null : (long?)value;
}
else {
    // handle case where myOtherVar couldn't be parsed
}
Run Code Online (Sandbox Code Playgroud)

  • @Dr.Zim:`Int64.Parse(myOtherVar)== 0?(long?)null:Int64.Parse(myOtherVar);`有效,因为存在从`long`到`long?`的隐式转换.那么,`(long?)null`的类型是`long?`和`Int64.Parse(myOtherVar)`有类型`long`,它有一个隐式转换为`long?`,因此编译器将表达式键入`long? `. (2认同)