可空类型和三元运算符:为啥是`? 10:null`禁止? [复制]
Posted
技术标签:
【中文标题】可空类型和三元运算符:为啥是`? 10:null`禁止? [复制]【英文标题】:Nullable types and the ternary operator: why is `? 10 : null` forbidden? [duplicate]可空类型和三元运算符:为什么是`? 10:null`禁止? [复制] 【发布时间】:2010-10-25 21:03:36 【问题描述】:我刚刚遇到了一个奇怪的错误:
private bool GetBoolValue()
//Do some logic and return true or false
然后,在另一种方法中,像这样:
int? x = GetBoolValue() ? 10 : null;
很简单,如果方法返回true,给Nullableint
x赋值10。否则,将 null 分配给 nullable int。但是,编译器抱怨:
错误 1 无法确定条件表达式的类型,因为
int
和<null>
之间没有隐式转换。
我要疯了吗?
【问题讨论】:
也许这会在编译器的未来版本中得到纠正,因为 'int' 和 '顺便说一句,C# 编译器的 Microsoft 实现实际上以一种非常微妙和有趣(对我而言)的方式错误地对条件运算符进行了类型分析。我的文章是 Type inference woes, part one (2006-05-24)。
【讨论】:
【参考方案2】:这是因为编译器通过其第二个和第三个操作数来确定条件运算符的类型,而不是根据您将结果分配给什么。整数和空引用之间没有直接转换,编译器可以使用它来确定类型。
【讨论】:
我不同意。我认为,自然的期望是条件表达式的类型将是第二个和第三个操作数类型的最小公分母。您将结果分配到的数据类型不需要在类型解析中发挥任何作用。【参考方案3】:编译器首先尝试计算右边的表达式:
GetBoolValue() ? 10 : null
10
是 int
文字(不是 int?
),null
是 null
。这两者之间没有隐式转换,因此出现错误消息。
如果将右侧表达式更改为以下表达式之一,则它会编译,因为在 int?
和 null
(#1) 之间以及 int
和 int?
(#2, #3)。
GetBoolValue() ? (int?)10 : null // #1
GetBoolValue() ? 10 : (int?)null // #2
GetBoolValue() ? 10 : default(int?) // #3
【讨论】:
你也可以写new int?()
。
或者更好的恕我直言:default(int?)
是的,编译器在将int
10 包装 到int?
之前需要此线索。请注意,另一种可能性是将int
10 装箱 到System.Int32
的基类或接口。例如GetBoolValue() ? (IFormattable)10 : null // #1B
或GetBoolValue() ? 10 : (IFormattable)null // #2B
就可以了。这种可能性可能是他们不使可空包装自动的原因。因为包装和装箱通常都是隐式转换。那就是 int? variable = 10;
和 IFormattable variable = 10;
都是合法的(前者包裹,后者盒子)。
我希望我的评论是在上下文中。我的要求是在字符串为 NULL 时将 null 传递给 Oracle 表编号列。针对上面的示例,我这样管理它: cmd.Parameters.Add("2", OracleDbType.Double).Value = String.IsNullOrEmpty(pNumberChar) ? (Double?)null : Convert.ToDouble(pNumberChar);【参考方案4】:
试试这个:
int? result = condition ? 10 : default(int?);
【讨论】:
【参考方案5】:试试这个:
int? x = GetBoolValue() ? 10 : (int?)null;
基本上发生的情况是条件运算符无法确定表达式的“返回类型”。由于编译器隐含地决定10
是int
,因此它决定这个表达式的返回类型也应该是int
。由于int
不能是null
(条件运算符的第三个操作数),它会报错。
通过将null
转换为Nullable<int>
,我们明确告诉编译器该表达式的返回类型应为Nullable<int>
。您也可以轻松地将 10
转换为 int?
并获得相同的效果。
【讨论】:
我知道我可以解决它,我只是好奇为什么会这样? 您可以进一步缩短:int? x = GetBoolValue() ? 10 : default;
【参考方案6】:
问题是三元运算符是根据您的第一个参数分配推断类型...10 在这种情况下,它是一个 int,而不是一个可为空的 int。
你可能会有更好的运气:
int? x = GetBoolValue() (int?)10 : null;
【讨论】:
【参考方案7】:只需添加一个显式演员表。
int? x = GetBoolValue() ? 10 : (int?)null;
混淆的是三元运算符 - 第二个参数是一个整数,第三个参数也应该是一个整数,并且 null 不适合。
【讨论】:
【参考方案8】:尝试以下方法之一:
int? x = GetBoolValue() ? (int?)10 : null;
int? x = GetBoolValue() ? 10 : (int?)null;
【讨论】:
我们可以再添加一个:int? x = GetBoolValue() ? 10 : 新的 int?();【参考方案9】:int? x = GetBoolValue() ? 10 : (int?)null;
你看到这个的原因是你在幕后使用 Nullable,你需要告诉 C# 你的“null”是 Nullable 的一个空实例。
【讨论】:
噢!安德鲁得到了他们的第一个。 +1 给他。以上是关于可空类型和三元运算符:为啥是`? 10:null`禁止? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
为啥 C# 6.0 在使用 Null 传播运算符时不允许设置非 null 可空结构的属性?