接线员'??' 不能应用于子类的类型的操作数

Joe*_*Joe 4 c# casting language-design

以下代码在Main函数的第二行的标题中给出了错误.

public class P {}

public class B : P {}

public class A : P {}

void Main()
{   
    P p = GetA()??GetB();
}

public A GetA() 
{
    return new A();
}

public B GetB()
{
    return new B();
}
Run Code Online (Sandbox Code Playgroud)

像这些简单的调整线

    p = (P)GetA()??GetB();
    or
    p = GetA()??(P)GetB();
Run Code Online (Sandbox Code Playgroud)

作品.

我很好奇为什么编译器不明白两者都是左侧容器的子类并允许没有强制转换的操作?

Ed *_* S. 6

左侧的参数类型必须与右侧的类型兼容,反之亦然.换句话说,存在必须从存在的隐式转换BA或从AB.

var a = x ?? y;
Run Code Online (Sandbox Code Playgroud)

在上面,如果存在隐式转换y,x那么类型将x成为表达式的类型.如果没有来自隐式转换yx,但存在从隐式转换xy,则该类型y变为表达式的类型.如果两个方向都没有转换,那么繁荣; 编译错误.从规格:

表达式的类型a ?? b取决于操作数类型之间可用的隐式转换.按优先顺序排列,类型为?? b是A0,A或B,其中A是a的类型,B是b的类型(假设b具有类型),如果A是可空类型,则A0是A的基础类型,否则A .具体来说,一个?? b处理如下:

•如果A不是可空类型或引用类型,则会发生编译时错误.

•如果A是可空类型,并且从b到A0存在隐式转换,则结果类型为A0.在运行时,首先评估a.如果a不为null,则打开a以键入A0,这将成为结果.否则,b被评估并转换为类型A0,这就成了结果.

•否则,如果从b到A存在隐式转换,则结果类型为A.在运行时,首先计算a.如果a不为null,则a成为结果.否则,b被评估并转换为类型A,这就是结果.

•否则,如果b具有类型B并且存在从A0到B的隐式转换,则结果类型为B.在运行时,首先计算a.如果a不为null,则打开a以键入A0(除非A和A0是相同的类型)并转换为类型B,这将成为结果.否则,b被评估并成为结果.

•否则,a和b不兼容,并发生编译时错误.