C# 无法确定条件表达式的类型,因为';int';及<;空>;

C# 无法确定条件表达式的类型,因为';int';及<;空>;,c#,nullable,C#,Nullable,为什么不编译 int? number = true ? 5 : null; 无法确定条件表达式的类型,因为在“int”和之间没有隐式转换 null没有任何可识别的类型-只需轻轻一推即可: int? number = true ? 5 : (int?)null; 规范(§7.14)规定,对于条件表达式b?x:y,有三种可能,要么x和y都有一个类型并且满足某些良好条件,要么只有x和y中的一个有一个类型并且满足某些良好条件,要么发生编译时错误。这里,“某些良好条件”意味着某些转换是可能的,我们将在

为什么不编译

int? number = true ? 5 : null;
无法确定条件表达式的类型,因为在“int”和之间没有隐式转换


null
没有任何可识别的类型-只需轻轻一推即可:

int? number = true ? 5 : (int?)null;
规范(§7.14)规定,对于条件表达式
b?x:y
,有三种可能,要么
x
y
都有一个类型并且满足某些良好条件,要么只有
x
y
中的一个有一个类型并且满足某些良好条件,要么发生编译时错误。这里,“某些良好条件”意味着某些转换是可能的,我们将在下面详细介绍

现在,让我们来看看规范中的相关部分:

如果
x
y
中只有一个具有类型,并且
x
y
都可以隐式转换为该类型,则这就是条件表达式的类型

这里的问题是

int? number = true ? 5 : null;
只有一个条件结果具有类型。这里的
x
int
文本,
y
null
,它没有类型
null
不能隐式转换为
int
1。因此,不满足“某些良好条件”,就会发生编译时错误

有两种解决方法:

int? number = true ? (int?)5 : null;
在这里,我们仍然是在这样的情况下,
x
y
中只有一个具有类型。请注意,
null
仍然没有类型,但编译器对此不会有任何问题,因为
(int?)5
null
都可以隐式转换为
int?
(§6.1.4和§6.1.5)

另一种方式显然是:

int? number = true ? 5 : (int?)null;
但现在我们必须阅读规范中的另一个条款来理解为什么这是可以的:

如果
x
具有类型
x
y
具有类型
y
,则

  • 如果存在从
    X
    Y
    的隐式转换(§6.1),而不是从
    Y
    X
    ,则
    Y
    是条件表达式的类型

  • 如果存在从
    Y
    X
    的隐式转换(§6.1),而不是从
    X
    Y
    ,则
    X
    是条件表达式的类型

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

这里的
x
类型为
int
y
类型为
int?
。没有从
int?
int
的隐式转换,但是有从
int
int?
的隐式转换,因此表达式的类型是
int?


1:进一步注意,在确定条件表达式的类型时忽略了左侧的类型,这是一个常见的混淆源。

如其他人所述,5是一个
int
,并且
null
不能隐式转换为
int

以下是解决此问题的其他方法:

int? num = true ? 5 : default(int?);
int? num = true ? 5 : new int?();

int? num = true ? 5 : null as int?;
int? num = true ? 5 : (int?)null;

int? num = true ? (int?)5 : null;
int? num = true ? 5 as int? : null;

int? num = true ? new int?(5) : null;
此外,无论您在哪里看到
int?
,您都可以在
C#9
中使用
Nullable

目标类型??然后呢? 有时是有条件的??和?:表达式在分支之间没有明显的共享类型。这种情况今天失败了,但如果存在两个分支都转换为的目标类型,C#9.0将允许这种情况:

或者你的例子:

// Allowed in C# 9.
int? number = true ? 5 : null;

或者你可以做
int?数字=真?5:null为int很好的答案抓住了要点。相关阅读:问题不在于
null
没有可识别的类型。问题是没有从
null
int
的隐式转换。细节。有趣的是
int?数字=真?5:(int?)空
int?数字=真?(int?)5:空都编译!!Scratch,Scratch我在我的文章中详细介绍了为什么会发生这种情况。很好地引用了规范来说明为什么会发生这种情况-+1!另一个选项是
newint?()
代替
(int?)null
。如果您有一个可为空的数据库字段类型,例如一个可为空的DateTime,并且您尝试将数据强制转换到
DateTime
,而实际上需要
(DateTime?
,这是一个很好的解释。最好的解释和示例-topas应该发生+1
// Allowed in C# 9.
int? number = true ? 5 : null;