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

时间:2011-05-26 11:48:46

标签: c# oop

我有以下课程:

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子句的行为存在很大差异?

2 个答案:

答案 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。那里没有隐式转换(例如,因为一个不是从另一个转换而来的)。但你可以继续并明确它并投下它(这是你在第二和第三个工作示例中所做的),因为 可以进行转换。