给出以下内容
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
场景中那样。
我不明白为什么编译器足够聪明,可以在一种情况下解决它,而在另一种情况下却不能解决。
答案 0 :(得分:7)
三元运算符的返回类型由内而外确定。它确定true / false子句的类型,并选择两者中更通用的子句。狗和猫都不是另一种的概括,因此不能将它们强制转换。但是狗和动物或动物和猫都可以。
first_expression
和second_expression
的类型必须相同,或者必须存在从一种类型到另一种类型的隐式转换。
另请参阅this answer,其中详细说明:
条件运算符类型分析是从内部到外部而不是从外部到内部进行的。条件运算符不知道将其结果分配给哪种类型,然后强制执行结果并替代那些类型。相反。它计算出结果和替代的类型,采用这两种类型中的更通用类型,然后验证可以分配通用类型。
答案 1 :(得分:4)
在第一个实例中,Dog
和Cat
实例分别隐式地向下转换为Animal
。
但是,在第二个表达式中,必须确定表达式的返回类型。因此,一种类型必须可以转换为其他类型。您可能希望编译器将其推断为Animal
,因为它们都继承自Animal
类,但是如果它们都实现其他接口怎么办?喜欢:
public class Dog : Animal, IFoo { }
public class Cat : Animal, IFoo { }
现在IFoo
也是三元运算的有效返回类型。
这就是为什么需要显式强制转换以避免歧义的原因。