多态null合并算子

时间:2014-08-11 09:58:22

标签: c# .net compiler-errors polymorphism operators

考虑

interface IResult {}
class Result : IResult {}
class Results : IResult {}

class Producer {
    private Results results;
    IResult DoSomething() {
        return results ?? new Result();
    }
}

这会因编译器错误而失败

Operator '??' cannot be applied to operands of type `Result` and `Results`

对我来说,这是出乎意料的行为。考虑到这一点,.NET框架可能会创建一个类型为Results的中间变量(左操作数)。右操作数Result的类型不同,因此会产生类型转换错误。这个假设是否正确?

如果是,为什么csc检测到中间变量属于IResult类型?

所以我将代码更改为

return results == null ? new Result() : results;

但这段代码错误

There is no explicit conversion between `Result` and `Results`

为什么呢?我不指望这个,因为两个实例都符合IResult。

2 个答案:

答案 0 :(得分:7)

因为:

return results ?? new Result();

实际上它会尝试将最后一个参数的值转换为与第一个参数相同的类型。编译器认为这是您需要的类型。它没有使用您分配给它的变量的类型。

你需要隐式演员。把它投到IResult,你就可以了:

return (IResult)results ?? new Result();

答案 1 :(得分:4)

嗯,这是预期的。由于ResultResults不是同一个类,因此它们只是实现了一个公共接口,但它们不能相互转换,这就是您收到错误的原因。

  

如果是,为什么csc检测到中间变量的类型为IResult?

这会引起歧义。如果您的类型实现了多个公共接口,例如IFoo,会发生什么。那么编译器应该选择IResult还是IFoo?你可以说它应该选择IResult因为返回类型但是应该发生什么呢这不是一个return语句,这可能是简单的赋值例如..所以简而言之,C#编译器没有&# 39;对类型做出假设。

C# Specification

中的7.13 The null coalescing operator也说明了这一点
  

表达式a ?? b的类型取决于操作数上可用的隐式转换。按优先顺序,a ?? b的类型为A0A,或B,其中Aa的类型(假设a有类型),Bb的类型(前提是b有a类型),如果A是可空类型,则A0是A的基础类型,否则是A.具体而言,a ?? b按如下方式处理:

     
      
  • [...]如果A存在并且存在从bA的隐式转换,则结果类型为A

    < / LI>   
  • [...]如果b的类型为B,且aB之间存在隐式转换,则结果类型为B. < / p>

  •   
  • 否则,ab 不兼容,并发生编译时错误。

  •