运营商'??'不能应用于子类类型的操作数

发布于 2024-12-11 01:59:57 字数 427 浏览 0 评论 0原文

以下代码给出了 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();
}

像这样对线路进行简单的调整

    p = (P)GetA()??GetB();
    or
    p = GetA()??(P)GetB();

就可以了。

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

The following code gives the error in the title on the second line in the Main function.

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();
}

A simple tweak to the line like these

    p = (P)GetA()??GetB();
    or
    p = GetA()??(P)GetB();

works.

I'm curious why the compiler doesn't understand that both are child classes of the left hand side container and allow the operation without the cast?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

日裸衫吸 2024-12-18 01:59:57

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

var a = x ?? y;

在上面,如果存在从 yx 的隐式转换,则 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 不为空,则 a 成为结果。否则,b 被计算并转换为类型 A,这就是结果。

• 否则,如果b 具有类型B 并且存在从A0 到B 的隐式转换,则结果类型为B。在运行时,首先对a 求值。如果 a 不为 null,则将 a 解包为类型 A0(除非 A 和 A0 是同一类型)并转换为类型 B,这将成为结果。否则,对 b 进行求值并成为结果。

• 否则,a 和 b 不兼容,并且出现编译时错误。

The type of the argument on the left hand side must be compatible with the type on the right hand side or vice versa. In other words, there must exist an implicit conversion from B to A or from A to B.

var a = x ?? y;

In the above, if there is an implicit conversion from y to x then the type of x becomes the type of the expression. if there is no implicit conversion from y to x, but there is an implicit conversion from x to y, then the type of y becomes the type of the expression. if no conversion exists in either direction, boom; compilation error. From the spec:

The type of the expression a ?? b depends on which implicit conversions are available between the types of the operands. In order of preference, the type of a ?? b is A0, A, or B, where A is the type of a, B is the type of b (provided that b has a type), and A0 is the underlying type of A if A is a nullable type, or A otherwise. Specifically, a ?? b is processed as follows:

• If A is not a nullable type or a reference type, a compile-time error occurs.

• If A is a nullable type and an implicit conversion exists from b to A0, the result type is A0. At run-time, a is first evaluated. If a is not null, a is unwrapped to type A0, and this becomes the result. Otherwise, b is evaluated and converted to type A0, and this becomes the result.

• Otherwise, if an implicit conversion exists from b to A, the result type is A. At run-time, a is first evaluated. If a is not null, a becomes the result. Otherwise, b is evaluated and converted to type A, and this becomes the result.

• Otherwise, if b has a type B and an implicit conversion exists from A0 to B, the result type is B. At run-time, a is first evaluated. If a is not null, a is unwrapped to type A0 (unless A and A0 are the same type) and converted to type B, and this becomes the result. Otherwise, b is evaluated and becomes the result.

• Otherwise, a and b are incompatible, and a compile-time error occurs.

不打扰别人 2024-12-18 01:59:57

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

因为这样就可以允许:

public class SqlConnection : object {}    
public class Random : object {}

public SqlConnection GetA() { return new SqlConnection(); }
public Random GetB() { return new Random(); }

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

I'm curious why the compiler doesn't understand that both are child classes of the left hand side container and allow the operation without the cast?

Because then this would be allowed:

public class SqlConnection : object {}    
public class Random : object {}

public SqlConnection GetA() { return new SqlConnection(); }
public Random GetB() { return new Random(); }

void Main()
{   
    var p = GetA() ?? GetB();
}
桜花祭 2024-12-18 01:59:57

运算符的操作数 ??应该是同一类型:

    P a = GetA();
    P b = GetB();
    P p = a ?? b;

the operands of the operator ?? should be of same type:

    P a = GetA();
    P b = GetB();
    P p = a ?? b;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文