[英]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.