Udostępnij za pośrednictwem


Exploring Extension methods – potential method invocation problems

Extension methods are one of the many great new features of C# 3.0. They basically allow you to declare static methods that appear to be instance methods of a type, even if you have no access to the type (sealed classes, etc). The key point is that you don’t need to recompile or even have source access to the type you are working with.

 

When do these extension methods get called? From the C# 3.0 specs (available in the CTP):

 

if the normal processing of the invocation finds no applicable instance methods (specifically, if the set of candidate methods for the invocation is empty), an attempt is made to process the construct as an extension method invocation.

 

So basically, it works as you would expect. If you have an instance method with name X, and an extension method with the same name, the instance method will be called. However, one thing that the spec doesn't talk about is what the rules are to decide between two potential method calls.

 

Take the following code

 

interface ITest {}

internal class BaseClass {}

internal class ExtendedClass : BaseClass, ITest {}

 

static void WriteSomething(BaseClass bc) {

    Console.WriteLine("BaseClass static");

}

static void WriteSomething(ITest test) {

    Console.WriteLine("ITest static");

}

ExtendedClass e1 = new ExtendedClass();

WriteSomething(e1);

 

What do you expect to have happen? Well, in this case, the compiler will complain, and let you know that "The call is ambiguous between the following methods or properties: …". This makes perfect sense, as there is no way to determine which method to call. However, let’s add another method

 

static void WriteSomething<T>(T bc) {

    Console.WriteLine("Generic static");

}

 

What do you think will happen here? Well, it turns out that the generic method will be called, and it will compile and run fine. Again, there is no confusion here, as the generic method can be called directly on the entended class, no casting needed.

 

So I haven’t talked about extension methods really. All of these examples use plain old C# 2.0 code. However, it turns out that extension methods have the exact same procedure to determine method invoking. Why is this behavior important?

 

Extension methods open up your type to the world, and there is very little control over what new methods get written.

 

If you use inheritance a lot in your application, and then someone comes along and declares a generic based method with the same name anywhere in the application, that method will now get called when you expected your base/interface based method to get called. Everything will compile correctly, so you’ll get a nice run-time exception (at best).  

 

Something to keep in mind

Comments

  • Anonymous
    September 12, 2006
    &amp;quot;Extension methods are one of the many great new features of C# 3.0. They basically allow you to

  • Anonymous
    August 09, 2007
    What about ambiguous extensions? You make one called 'In' and a developer gets it via a using statement (e.g. using EricksExtensions) I make an extension called 'In' and a developer wants to use that also. (e.g. using EdsExtensions) obj.In is now ambiguous. How to tell the which one to resolve?

  • Anonymous
    August 09, 2007
    Ed, The rules basically say that the one in the "closest" namespace to you gets called. If two methods are the same distance away, then you should get a compiler error. All part of the learning curve around these new techniques... Thanks, Erick