C# CS0173具有不同返回类型的三元上的编译错误

C# CS0173具有不同返回类型的三元上的编译错误,c#,oop,C#,Oop,考虑这个例子: using System.IO; using System; class A{} class B : A{} class C : A{} class Program { static void Main() { GetSomething1(true); } static A GetSomething1(bool oneOrAnother) { return oneOrAnother ? new B()

考虑这个例子:

using System.IO;
using System;

class A{}

class B : A{}
class C : A{}

class Program
{
    static void Main()
    {
        GetSomething1(true);
    }

    static A GetSomething1(bool oneOrAnother)
    {
        return oneOrAnother ? new B() : new C(); // throws a compile error
    }

    static A GetSomething2(bool oneOrAnother)
    {
        return oneOrAnother ? (A)(new B()) : new C(); // no error
    }

    static A GetSomething3(bool oneOrAnother)
    {
        return oneOrAnother ? new B() : (A)(new C()); // no error
    }

    static A GetSomething4(bool oneOrAnother)
    {
        return oneOrAnother ? (A)(new B()) : (A)(new C()); // no error
    }
}


GetSomething1中的三元数生成

错误CS0173:无法确定条件表达式的类型,因为'B'和'C'之间没有隐式转换。


我无法理解为什么B和C都可以完美地转换为A(它们从A扩展而来),并且在进一步的示例中,仅显式转换其中一个就足以获得三元工作

三元表达式的规则是两个可能的结果必须是相同的类型,或者其中一个可以安全地抛给另一个。编译器不会去寻找一个安全的第三个基类,它可以同时用于这两个基类。因此,您必须指定这两个表达式中的一个是基类,比如
?(A) new B():new C()
,这是Eric Lippert为C#9提出的:“如果两种类型都不属于另一种类型,那么请注意,我们不会试图找到“最近的包含类型”。有趣的是,Java允许这样做……据我所知,C#9建议,他们打开了一些表达式,允许在存在目标类型时自动转换为目标类型。在问题中的代码中,第一个表达式的目标类型将是
A
,并且由于
B
C
都可以强制转换为
A
,因此这是允许的。您仍然不能执行
var x=one或other吗?新的B():新的C()因为没有要定位的类型,但是您可以执行
A x=…
。基本上,如果我理解正确,您可以将表达式的使用方式添加到混合中,以及使用预期的类型。三元表达式的规则是,两个可能的结果必须是相同的类型,或者其中一个可以安全地转换为另一个。编译器不会去寻找一个安全的第三个基类,它可以同时用于这两个基类。因此,您必须指定这两个表达式中的一个是基类,比如
?(A) new B():new C()
,这是Eric Lippert为C#9提出的:“如果两种类型都不属于另一种类型,那么请注意,我们不会试图找到“最近的包含类型”。有趣的是,Java允许这样做……据我所知,C#9建议,他们打开了一些表达式,允许在存在目标类型时自动转换为目标类型。在问题中的代码中,第一个表达式的目标类型将是
A
,并且由于
B
C
都可以强制转换为
A
,因此这是允许的。您仍然不能执行
var x=one或other吗?新的B():新的C()因为没有要定位的类型,但是您可以执行
A x=…
。基本上,如果我理解正确,您可以将表达式的使用方式添加到混合中,以及使用预期的类型。