I just hit a situation where a method dispatch was ambiguous and wondered if anyone could explain on what basis the compiler (.NET 4.0.30319) chooses what overload to call
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());
}
In any case, why does the compiler not warn me or even why does it compile?
Thank you very much for any answers.
It follows the rules in section 7.5.3.2 of the C# 4 specification (“Better function member”).
First (well, after seeing that both methods are applicable) we need to check the conversions from argument types to parameter types. In this case it’s reasonably simple because there’s only one argument. Neither conversion of argument type to parameter type is “better” because both are converting from
ConcreteAtoIfaceA. It therefore moves on to the next set of criteria, including this:So even though the conversion is equally good, the overload using
IfaceAdirectly (rather than via delegates) is deemed “better” because a parameter of typeIfaceAis more specific than a parameter of typeT.There’s no way of getting the compiler to warn on this behaviour – it’s just normal overload resolution.