将if else转换为三元数失败

时间:2018-08-26 01:10:17

标签: c# ternary-operator

给出以下内容

public abstract class Animal { }
public class Dog : Animal { }
public class Cat : Animal { }

我可以写一个方法

public Animal UsingIf(bool returnDog)
{
    if (returnDog)
        return new Dog();
    else
        return new Cat();
}

为什么使用三元表达式表示等效结果

public Animal UsingTernary(bool returnDog) =>
    returnDog ? new Dog() : new Cat();

导致以下编译错误

CS0173 Type of conditional expression cannot be determined because there is no implicit conversion between 'UserQuery.Dog' and 'UserQuery.Cat

我可以通过转换三元组的一部分(或同时转换两者)来解决

public Animal UsingTernary(bool returnDog) =>
    returnDog ? new Dog() : (Animal) new Cat();

但是为什么编译器不能将第二种方法转换为与第一种方法等效?

编辑:我很感谢每个人的回答,但是尽管从技术角度来看它们是正确的,但没有人真正回答过这个问题的症结所在。

为什么编译器不能将第二种方法转换为与第一种方法等效?

即使在界面情况下也可以使用

public interface IFoo { }
public abstract class Animal { }
public class Dog : Animal, IFoo { }
public class Cat : Animal, IFoo { }

public IFoo UsingIf(bool returnDog)
{
    if (returnDog)
        return new Dog();
    else
        return new Cat();
}

为什么编译器不能使用该方法的返回类型,就像在if /else场景中那样。

我不明白为什么编译器足够聪明,可以在一种情况下解决它,而在另一种情况下却不能解决。

2 个答案:

答案 0 :(得分:7)

三元运算符的返回类型由内而外确定。它确定true / false子句的类型,并选择两者中更通用的子句。狗和猫都不是另一种的概括,因此不能将它们强制转换。但是狗和动物或动物和猫都可以。

来自C# specification

  

first_expressionsecond_expression的类型必须相同,或者必须存在从一种类型到另一种类型的隐式转换。

另请参阅this answer,其中详细说明:

  

条件运算符类型分析是从内部到外部而不是从外部到内部进行的。条件运算符不知道将其结果分配给哪种类型,然后强制执行结果并替代那些类型。相反。它计算出结果和替代的类型,采用这两种类型中的更通用类型,然后验证可以分配通用类型。

答案 1 :(得分:4)

在第一个实例中,DogCat实例分别隐式地向下转换为Animal

但是,在第二个表达式中,必须确定表达式的返回类型。因此,一种类型必须可以转换为其他类型。您可能希望编译器将其推断为Animal,因为它们都继承自Animal类,但是如果它们都实现其他接口怎么办?喜欢:

public class Dog : Animal, IFoo { }
public class Cat : Animal, IFoo { }

现在IFoo也是三元运算的有效返回类型。

这就是为什么需要显式强制转换以避免歧义的原因。