Null合并运算符和使用

时间:2015-11-24 15:53:40

标签: c#

为什么我不能使用空合并运算符(??)和使用as的转换? 根据我的理解,使用as进行投射会产生null,如果类型不是实例的类型,那么我认为它会尝试表达式的正确部分。

这是我的意思的一个例子:

void Main()
{
    a instance = new c();

    var test = (instance as d) ?? (instance as c) ?? (instance as b);
}

public class a {}
public class b : a {}
public class c : a {}
public class d : a {}

我得到的错误:

Operator '??' cannot be applied to operands of type 'UserQuery.d' and 'UserQuery.c'

我理解在这种情况下使用var是不合适的,但即使使用dynamica(基类型),我也会得到相同的错误消息。该问题似乎与??运算符有关。

4 个答案:

答案 0 :(得分:3)

您需要能够在编译时定义test变量的类型。您尝试合并的3个表达式都是不同的类型(dcb)。

更具体地说,合并运算符需要两个表达式基本上是相同的类型。您的每个合并操作都在操作员的每一侧以不同的类型执行。要阅读有关此要求的完整详细信息,请查看以下答案:https://stackoverflow.com/a/8898305/674326

您可以将每个表达式转换为a,然后您就可以编译,因为test的类型可以确定为a。但那会破坏你的练习的目的吗?

答案 1 :(得分:3)

var是一个编译时构造。它不支持动态输入。

因此,你要做的事情绝对毫无意义。 test唯一可能的类型是a - 您已经拥有该类型。

有意义(并且是合法的)将是这样的:

var someValue = (obj as d)?.someProperty ?? (obj as c)?.someOtherProperty;

在这种情况下,没有动态类型 - 我们只是采用不同的方式从两种不同的类型中获取等效值。然而,与例如相比,即使这听起来也是一个坏主意。使用适当的多态性,或者至少使用dynamic

答案 2 :(得分:2)

这与as operator无关,只是因为编译器无法确定(d ?? c)的返回类型。 您可以通过将至少一个操作数强制转换为a

来解决此问题
var test = (instance as d) ?? (a) (instance as c) ?? (instance as b);

这是观察此行为的较短样本

c instancec = new c();
d instanced = new d();

a foo = instancec ?? instanced; // Compile error even if we declare foo as a

答案 3 :(得分:0)

稍微简化代码:

var test = (instance as d) ?? (instance as c);

您期望test的类型是什么?是d还是c?该类型必须仅在编译时确定。编译器不会为您隐式地将它强制转换为相应的基类型。所以你需要像@ Ksv3n建议那样手动完成。