簡體   English   中英

多態空合並運算符

[英]Polymorphic null coalescing operator

考慮

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。

因為這:

return results ?? new Result();

實際上,它嘗試將最后一個參數的值轉換為與第一個參數相同的類型。 編譯器認為這是您需要的類型。 它不使用您要為其分配變量的類型。

您需要隱式轉換。 將其IResultIResult

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

好吧,這是預期的。 因為ResultResults不是同一類,所以它們僅實現一個公共接口,但不能相互轉換,這就是為什么會出現錯誤的原因。

如果是,為什么csc無法檢測到中間變量的類型為IResult?

這會引起歧義。 IFoo說,如果您的類型實現多個公共接口,將會發生什么。 然后編譯器應該選擇IResult還是IFoo 您可以說由於返回類型而應該選擇IResult ,但是應該發生的事情不是返回語句,例如,這可能是簡單的賦值。因此,簡而言之, C#編譯器不會對類型進行假設。

C# Specification中的7.13 The null coalescing operator也對此進行了說明。

類型表達a ?? b a ?? b取決於所隱式轉換可用偏好operands.In量級,類型a ?? b a ?? bA0AB ,其中A是的類型a (假設一個具有類型), B是類型b (其中,b的一個類型)和A0是如果底層類型A的是可為空的類型,否則為A。 具體來說, a ?? b a ?? b的處理如下:

  • [...]如果存在A且存在從bA的隱式轉換,則結果類型為A

  • [...]如果b具有類型B並且存在從aB的隱式轉換,則結果類型為B。

  • 否則, ab 不兼容,並且發生編譯時錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM