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

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

 long? myVar = Int64.Parse( myOtherVar) == 0 ? null : Int64.Parse( myOtherVar); 

但是,这成功了:

 if( Int64.Parse( myOtherVar) == 0) myVar = null; else myVar = Int64.Parse( myOtherVar); 

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

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

 Int64.Parse(myOtherVar) == 0 ? null : Int64.Parse(myOtherVar) 

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

 Int64.Parse(myOtherVar) 

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

从C#规范的第7.14节开始:

formsb ? x : y条件表达式b ? x : y b ? x : y ….

?:运算符的第二个和第三个操作数xy控制条件表达式的类型。

(1)如果xX型, yY

一个。 如果从XY存在隐式转换(第6.1节),而不是从YX ,则Y是条件表达式的类型。

湾 如果从YX存在隐式转换(第6.1节),而不是从XY ,则X是条件表达式的类型。

C。 否则,不能确定表达式类型,并发生编译时错误。

(2)如果xy只有一个具有类型,并且xy都可以隐式转换为该类型,那么这就是条件表达式的类型。

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

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

纠正这个替代

 Int64.Parse(myOtherVar) 

 (long?)Int64.Parse(myOtherVar) 

现在,之所以如此

 myVar = null; 

可以将myVar声明为long? 是因为编译器知道存在从nulllong?的隐式转换long?

最后,如果myOtherVar无法解析为long ,则会抛出myOtherVar 。 请注意,您还要执行两次解析,这是不必要的。 更好的模式是

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

由于三元运算符的最后部分,您的运算符用法返回Int64而不是nullableInt64 。 如果您改为:

 long? myVar = Int64.Parse( myOtherVar) == 0 ? null : (long?)Int64.Parse( myOtherVar); 

这样你回来的long? 相反,所以null不需要转换为Int64

此外,您将在代码中两次转换值,不必要地(一次测试,一次获取值)。 您的代码可能更好:

 long? tempVar = Int64.Parse(myOtherVar); long? myVar = tempVar==0? null : tempVar; 

我相信你的意思是说:

  myVar = value == 0 ? null : (long?)value; 

代替

  myVar = value == 0 ? null : value; 

我喜欢’out’变量的用法。 谢谢。

这将有效:

 long? myVar = (long?)myOtherVar == 0 ? null : (long?)myOtherVar; 

..对于那些喜欢简短答案的人。

编译器尝试从左到右评估表达式

 long? myVar = Int64.Parse( myOtherVar) == 0 ? null : Int64.Parse( myOtherVar); 

int64.parse方法返回long值而不是nullable long值。 所以nullInt64.Parse( myOtherVar);之间没有转换Int64.Parse( myOtherVar); 所以,试试这个吧

 long? myVar = Int64.Parse(myOtherVar) == 0 ? (long?) null : Int64.Parse(myOtherVar); 

要么
long? myVar = Int64.Parse(myOtherVar) == 0 ? null : (long?) Int64.Parse(myOtherVar);