簡體   English   中英

c#通用重載方法調度模糊

[英]c# Generic overloaded method dispatching ambiguous

我剛剛遇到一個方法調度模糊的情況,並想知道是否有人可以解釋編譯器(.NET 4.0.30319)選擇什么過載調用的基礎

interface IfaceA
{

}

interface IfaceB<T>
{
    void Add(IfaceA a);
    T Add(T t);
}

class ConcreteA : IfaceA
{

}

class abstract BaseClassB<T> : IfaceB<T>
{
    public virtual T Add(T t) { ... }
    public virtual void Add(IfaceA a) { ... }
}

class ConcreteB : BaseClassB<IfaceA>
{
    // does not override one of the relevant methods
}

void code()  
{
    var concreteB = new ConcreteB();

    // it will call void Add(IfaceA a)
    concreteB.Add(new ConcreteA());
}

在任何情況下,為什么編譯器不會警告我,甚至為什么編譯? 非常感謝您的任何答案。

它遵循C#4規范 (“更好的功能成員”)第7.5.3.2節中的規則。

首先(在看到兩種方法都適用之后 ),我們需要檢查從參數類型到參數類型的轉換。 在這種情況下,它相當簡單,因為只有一個參數。 參數類型到參數類型的轉換都不是“更好”,因為它們都是從ConcreteA轉換為IfaceA 因此,它轉向下一組標准,包括:

否則,如果MP具有比MQ更多的特定參數類型,則MP優於MQ。 設{R1,R2,...,RN}和{S1,S2,...,SN}表示MP和MQ的未實例化和未展開的參數類型。 MP的參數類型比MQ更具體,如果對於每個參數,RX的特定性不低於SX,並且對於至少一個參數,RX比SX更具體:特定於SX:

  • 類型參數不是非類型參數的特定參數。
  • ...

因此即使轉換同樣好,直接使用IfaceA (而不是通過委托)的過載也被認為是“更好”,因為IfaceA類型的參數比類型T的參數更具體。

沒有辦法讓編譯器警告這種行為 - 這只是正常的重載決議。

因為編譯器首先選擇最具體的。

如果你這樣打電話怎么辦:

void code()   
{ 
    var concreteB = new ConcreteB(); 

    IfaceA  x = concreteB.Add(new ConcreteA()); 
} 

這有點讓我想起Jon Skeet的BrainTeaser中的“類型推斷a-go-go”。 如果您不想信任編譯器,可能需要通過調用Add<ConcreteA>(new ConcreteA())來強制選擇它。

暫無
暫無

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

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