使用条件运算符时没有隐式转换

Ale*_*der 15 c# oop

我有以下课程:

abstract class AClass { }
class Foo : AClass { }
class Bar : AClass { }
Run Code Online (Sandbox Code Playgroud)

当我试图使用它们时:

AClass myInstance;
myInstance = true ? new Foo() : new Bar();
Run Code Online (Sandbox Code Playgroud)

此代码将无法编译,因为"无法确定条件表达式的类型,因为'CSharpTest.Class1.Foo'和'CSharpTest.Class1.Bar'之间没有隐式转换"

但是以下样本编译好了:

if (true)
{
    myInstance = new Foo();
}
else
{
    myInstance = new Bar();
}
Run Code Online (Sandbox Code Playgroud)

这也没问题:

myInstance = true ? (AClass) new Foo() : new Bar();
Run Code Online (Sandbox Code Playgroud)

要么

myInstance = true ? new Foo() : (AClass) new Bar();
Run Code Online (Sandbox Code Playgroud)

为什么条件运算符和if子句的行为有如此大的差异?

Håv*_*d S 16

这是预期的行为.

由于X和Y之间不存在隐式转换(即使它们共享一个公共库,它们之间也没有隐式转换),您需要显式地(至少)将其中一个转换为基类,以便存在隐式转换.

C#规范的详细解释:

运算?:符的第二个和第三个操作数控制条件表达式的类型.设X和Y是第二个和第三个操作数的类型.然后,

如果X和Y是相同的类型,那么这是条件表达式的类型.

否则,如果从X到Y存在隐式转换(第6.1节),而不是从Y到X,则Y是条件表达式的类型.

否则,如果从Y到X存在隐式转换(第6.1节),而不是从X到Y,则X是条件表达式的类型.

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


Tim*_*Tim 5

三元运算符与 if 子句之间并没有太大的区别,而是您的语句中的区别。

在您的第一个工作示例中,您在 Foo 和 AClass 或 Bar 和 AClass 之间进行转换,这显然没问题。

在第二个工作示例中,您告诉三元运算符查看 AClass 和 Bar。在第三个工作示例中,您告诉三元运算符查看 Foo 和 AClass。那些显然有明显的转换。

在非工作示例中,您告诉它查看 Foo 和 Bar。那里没有隐式转换(例如,因为一个转换不是从另一个派生的)。但是您可以继续明确它并进行转换(这就是您在第二个和第三个工作示例中所做的事情),因为有可用的转换。