我有以下课程:
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子句的行为存在很大差异?
答案 0 :(得分:16)
这是预期的行为。
由于X和Y之间不存在隐式转换(即使它们共享一个公共库,它们之间也没有隐式转换),您需要显式转换(至少)其中一个到基类,以便存在隐式转换。
C#规范的详细解释:
?:
运算符的第二个和第三个操作数控制条件表达式的类型。设X和Y是第二个和第三个操作数的类型。然后,如果X和Y的类型相同,那么这就是条件表达式的类型。
否则,如果从X到Y存在隐式转换(第6.1节),而不是从Y到X, 然后Y是条件表达式的类型。
否则,如果存在从Y到X的隐式转换(第6.1节),而不是从X到Y, 那么X就是条件表达式的类型。
否则,无法确定表达式类型,并发生编译时错误。
答案 1 :(得分:4)
三元运算符与if子句之间没有太大区别,它在你的语句中有所不同。
在你的第一个工作示例中,你在Foo和AClass或Bar和AClass之间进行转换,这显然很好。
在您的第二个工作示例中,您告诉三元运算符查看AClass和Bar。在第三个工作示例中,您告诉三元运算符查看Foo和AClass。那些显然有明显的转换。
在非工作示例中,您告诉它要查看Foo和Bar。那里没有隐式转换(例如,因为一个不是从另一个转换而来的)。但你可以继续并明确它并投下它(这是你在第二和第三个工作示例中所做的),因为 可以进行转换。