Oww, my brain hurts. Extension methods *will* cause me grief.

As a consultant, a task that I’m commonly asked to perform is to troubleshoot applications in need of repair.  The underlying source code and architecture for many applications in need of repair has, let’s say, “problems”.  One of the issues I run into with circumstances like this is the source code was not well organized, not well thought out, or not well managed as it evolved.  This type of code has poor style, poor coding habits, and often the programmers have code stepping all over other code through lack of cohesion and excessive coupling. 


Believe me, as Visual Studio codenamed “Orcas” is released and proceeds into production development environments, I fully expect my life to get worse with increased fragility of code bases.  I ran into a lovely compile error today with the most recent .NET Framework 3.5 that confirms my fears. Essentially, the code has two extension methods with the same name and the same number of arguments in two different namespaces.  The first argument is the same in each, but the second is different; and, in fact, one is a reference type while the other is a value type.  In code that uses one extension method (the one with the second argument of reference type), simply by adding a using statement for the other namespace, caused the following error to occur:


test.cs(14,26): error CS1928: ‘string’ does not contain a definition for
        ‘IsPlural’ and the best extension method overload
        ‘Peter.Extensions.IsPlural(string, int)’ has some invalid arguments
test.cs(14,40): error CS1503: Argument ’2′: cannot convert from ‘<null>’ to
        ‘int’


Hmm, this error confirms that there is more than one IsPlural extension method and goes on to tell me that the “best” override has invalid arguments.  Huh?  How is it the best if it has invalid arguments?  Why would it consider passing null where a value type is expected the “best” override?  I really hope this doesn’t make it into RTM.


Oww, by brain hurts.

8 thoughts on “Oww, my brain hurts. Extension methods *will* cause me grief.”

  1. I think extension methods are something that are going to cause us all grief! We’ve spent years trying to convince people of the value of good class library design and encapsulation, and in one easy step we’re throwing it all away and saying “just implement whatever you want on any object”. No longer will people file bugs about unsuitable methods in class libraries being developed, they will just implement their own versions because its “easier”.

    Reading code it will now be impossible to tell which methods really exist on which objects, and especially as it will allow you to overload methods that really exist with ones that don’t.

    And for what? So you can write someObj.NewMethod() rather than NewMethod(someObj)? Great. Thanks. I’ve worked on many large scale projects and have never heard people complaining about this. It’s a non-issue. Extension methods are an answer to a question that nobody ever asked. Actually – that’s a good title – I might have to write a longer version of this rant at some point :)

  2. I home that Microsoft takes care about that, but we need dynamic languages features to be productive. I think that everythink slowly moves towards declarative domain specific languages (DSL) at all fronts (gui, database, workflows, …), so we need apropriate flexibility to code it well. But some “safety” keywords like “extendable” (?) will be IMHO good to have for classes ….. howgh!

  3. Just to provide a contrary view-point, I don’t think they’ll be that bad, myself – and I certainly see how they can increase readability.

    They’re useful when you want the code to explain what its purpose is rather than how exactly it achieves it.

    Of course they can be abused – extending the same type with the same extension method name in different namespaces is asking for trouble – but when used judiciously I think they’ll be very useful. Being able to chain methods together can make things *much* more readable IMO (think fluent interfaces).

    Small point of correction Peter: the error message correctly talked about overloads, not overrides. If it had mentioned overrides I’d have been just as annoyed as you, but fortunately it didn’t. As for why the method is “best” if it’s got incompatible arguments: it had the right *number* of arguments, which makes it “better” in many senses than an overload containing 100 arguments. That’s not new with extension methods.

    Jon

  4. Jon, yes, the correct term is “overload”, not “override”.

    In the context of having to work with other people’s code with “poor style” and “poor coding habits”, etc.; using extension methods for increased readability seems unlikely.

  5. It’s certainly something to keep carefully controlled. If you’re not working with good people, it could be easier to ban it than to try to only apply it appropriately.

    I’ll be happy to use it though :)

    Jon

  6. I’ll be happy to use extension methods when there’s some sort of scoping. Pulling in all extension methods through a simple using directive means we’ll have to go back to the dark ages of global functions and prefix our function names with something to keep them unique. Instead of “static uint WordCount(this String text){/*…*/}” I’ll have to use something like “static uint PRCountWords(this String text){/*…*/}” in case one of the namespaces I reference and import decides to use the same name. Otherwise we’re forced to always use them as static methods, which defeats the purpose of an extension method.

  7. I think the way to keep things unique is not to overuse extension methods to start with. I agree that the way of making them available pretty much sucks, too.

    Personally I intend to keep extension methods in namespaces which contain nothing *but* extension methods. That way I won’t use them unless I’ve explicitly tried to.

    Jon

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>