Operator '??' cannot be applied to operands of type for child classes

↘锁芯ラ 提交于 2019-12-23 15:22:45

问题


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?


回答1:


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.




回答2:


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



回答3:


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

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


来源:https://stackoverflow.com/questions/7829903/operator-cannot-be-applied-to-operands-of-type-for-child-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!