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

我有以下课程:

abstract class AClass { } class Foo : AClass { } class Bar : AClass { } 

当我试图使用它们时:

 AClass myInstance; myInstance = true ? new Foo() : new Bar(); 

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

但是以下样本编译好了:

 if (true) { myInstance = new Foo(); } else { myInstance = new Bar(); } 

这也没问题:

 myInstance = true ? (AClass) new Foo() : new Bar(); 

要么

 myInstance = true ? new Foo() : (AClass) new Bar(); 

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

这是预期的行为。

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

C#规范的详细解释:

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

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

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

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

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

三元运算符与if子句之间没有太大的区别,它在你的语句中有所不同。

在你的第一个工作示例中,你在Foo和AClass或Bar和AClass之间进行转换,这显然很好。

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

在非工作示例中,您告诉它要查看Foo和Bar。 那里没有隐式转换(例如,因为一个不是从另一个派生而来的)。 但是你可以继续并明确它并投下它(这是你在第2和第3个工作示例中所做的),因为有可用的转换。