I'm having trouble getting the compiler to fix the correct overload for the extension method. The best way to explain me a little code. Here's a LINQPad script that demonstrates the problem. This does not compile due to the problem I am facing:
void Main(){
new Container<A>().Foo(a=>false);
}
interface IMarker{}
class A : IMarker{
public int AProp{get;set;}
}
class B : IMarker{
public int BProp{get;set;}
}
class Container<T>{}
static class Extensions{
public static void Foo<T>(this T t, Func<T, bool> func)
where T : IMarker{
string.Format("Foo({0}:IMarker)", typeof(T).Name).Dump();
}
public static void Foo<T>(this Container<T> t, Func<T, bool> func){
string.Format("Foo(Container<{0}>)", typeof(T).Name).Dump();
}
}
The error I am getting is:
The call is ambiguous between the following methods or properties: ' Extensions.Foo<Container<A>>(Container<A>, System.Func<Container<A>,bool>)' and ' Extensions.Foo<A>(Container<A>, System.Func<A,bool>)'
It seems to me that this is not ambiguous. The first method will not take value Container<T>, but only IMarker. It seems that the general restrictions do not help in overload resolution, but in this version of the code they look like this:
void Main(){
new A().Bar();
new A().Foo(a=>a.AProp == 0);
new A().Foo(a=>false);
new A().Foo(a=>{
var x = a.AProp + 1;
return false;
});
new Container<A>().Bar();
new Container<A>().Foo(a=>a.AProp == 0);
new Container<A>().Foo(a=>{
var x = a.AProp + 1;
return false;
});
}
interface IMarker{}
class A : IMarker{
public int AProp{get;set;}
}
class B : IMarker{
public int BProp{get;set;}
}
class Container<T>{}
static class Extensions{
public static void Foo<T>(this T t, Func<T, bool> func)
where T : IMarker{
string.Format("Foo({0}:IMarker)", typeof(T).Name).Dump();
}
public static void Foo<T>(this Container<T> t, Func<T, bool> func){
string.Format("Foo(Container<{0}>)", typeof(T).Name).Dump();
}
public static void Bar<T>(this T t) where T : IMarker{
string.Format("Bar({0}:IMarker)", typeof(T).Name).Dump();
}
public static void Bar<T>(this Container<T> t){
string.Format("Bar(Container<{0}>)", typeof(T).Name).Dump();
}
}
This compiles and produces the expected results:
(A: IMarker)
Foo (A: IMarker)
Foo (A: IMarker)
Foo (A: IMarker)
( <A> )
Foo ( <A> )
Foo ( & , A > )
, , , Container<T>. Bar , . Foo , , . , , , .
, ? - , ? # 4, # 6.