13

I'm a bit confused about how extension methods work.

If I'm reading this correctly http://msdn.microsoft.com/en-us/library/bb383977.aspx and this If an extension method has the same signature as a method in the sealed class, what is the call precedence?.

Then the following should write out "Instance", but instead it writes "Extension method".

interface IFoo
{
}

class Foo : IFoo
{
    public void Say()
    {
        Console.WriteLine("Instance");
    }
}

static class FooExts
{
    public static void Say(this IFoo foo)
    {
        Console.WriteLine("Extension method");
    }
}

class Program
{
    static void Main(string[] args)
    {
        IFoo foo = new Foo();
        foo.Say();
    }
}

Appreciate any help in clarifying the behavior.

Community
  • 1
  • 1
Dax70
  • 1,051
  • 1
  • 8
  • 16
  • Are you sure overriding a built-in method with an extension method compiles? – kenny Sep 22 '11 at 20:36
  • On second glance or compiling it, the interface doesn't have Say(), so what you have calls the extension method. With Save() in the interface the compiler complains with 'C:\projects\_play\ExtensionMethods\Program.cs(2,1): error CS0116: A namespace cannot directly contain members such as fields or methods' – kenny Sep 22 '11 at 20:41

2 Answers2

15

The big difference here is that you have defined an extension method for the IFoo interface, and your foo variable is of type IFoo.

If your code was to look like this:

Foo foo = new Foo();
foo.Say()

The Foo.Say() method would be executed, not the extension method.

I wish I could give you a thorough explanation on why this is but I can only cover the basic mechanism. As your variable was of IFoo type and not of Foo, when the compiler tried to determine what methods were available, it looked past any non-interface methods of the Foo class (as it should). However, the extension method Say() was available, so it invoked this.

WiseGuyEh
  • 18,584
  • 1
  • 20
  • 20
  • 2
    To add to this, when you use `IFoo foo = ..`, the type of foo is `IFoo` even though it points to an instance of `Foo`. `Foo foo...` calls the method on the object, `IFoo foo` causes `Say()` to Expand to `FooExts.Say(foo)`. Run `ildasm` and drop the .exe into it to see the IL. – Joseph Yaduvanshi Sep 22 '11 at 20:47
4

In your Main, foo is declared as IFoo. When the compiler looks for a method Say, it finds only the extension method. This is because the instance method is declared in Foo, not in IFoo. The compiler doesn't know that the variable foo happens to contain a instance of Foo; it just looks at the type the variable is declared of.

dtb
  • 213,145
  • 36
  • 401
  • 431