Quoting the C# specification:
7.6.5.2 Extension method invocations
In a method invocation (§7.5.5.1) of
one of the formsexpr . identifier ( )
expr . identifier ( args )
expr . identifier < typeargs > ( )
expr . identifier < typeargs > ( args )
if the normal processing of the
invocation finds no applicable
methods, an attempt is made to process
the construct as an extension method
invocation. If expr or any of the args
has compile-time type dynamic,
extension methods will not apply.The objective is to find the best
type-name C, so that the corresponding
static method invocation can take
place:C . identifier ( expr )
C . identifier ( expr , args )
C . identifier < typeargs > ( expr )
C . identifier < typeargs > ( expr , args )
An extension method Ci.Mj is eligible
if:· Ci is a non-generic,
non-nested class· The name of Mj is identifier
· Mj is accessible and
applicable when applied to the
arguments as a static method as shown
above· An implicit identity,
reference or boxing conversion exists
from expr to the type of the first
parameter of Mj.
Since DoSomethingElse(foo) compiles but foo.DoSomethingElse() doesn’t, it seems like a compiler bug in overload resolution for extension methods: an implicit reference conversion exists from foo to IFoo<IBase>.