Why I don’t like C# extension methods

When I first became aware of the Extension Method in C#, my reaction was similar to that of a lot of people–I thought it was a pretty neat trick. For anyone not familiar with extension methods, they are a construct introduced in C# along with LINQ to allow ‘extension’ of a class. Here’s an example:

public static class Extensions
{
    public static string GetWordCount(this string str)
    {
        return str.Split(' ').Length;
    }
}

//Client code looks like:
public void SomeMethod(string str)
{
    if(str.GetWordCount() > 1)
    {
        //Do multiple word stuff
    }
    else
    {
        /Do single word stuff
    }
}

What’s going on behind the scenes here is that Microsoft introduced syntactic sugar on standard static methods. An extension method is really just a static method, and as far as the compiler is concerned, the client code is no different than it would be if you called “Extensions.GetWordCount(str);”

The advantages are immediately obvious. You can abstract verbose and redundant common idioms into these methods, favoring instead descriptive terminology. You can make it look as though GetWordCount() is a method of string, even though it isn’t. This means that, done right, you can create the appearance of enhanced classes without modifying the classes themselves. If you keep these methods well organized, they seem a natural enhancement to the language. And perhaps the most powerful thing of all is that you can extend library classes that are sealed or have non-virtual methods, or you can supply enhancements to your own API for others without the risk of introducing breaking changes.

But in spite of those benefits, something bothered me about this idea. I couldn’t quite put my finger on it for a long time. The drawbacks that one that might see in a google search or realize on his own include decoupling class-specific functionality from that class (i.e. violating encapsulation) and the fact that you’re favoring free-floating static utility over instance methods. There is also the possibility for naming collisions if you write an extension method with the same signature as an instance method. There is the confusion that one might experience not knowing through intellisense whether you were dealing with a native method of some class or an afterthought that somebody tacked on. But all of those drawbacks seemed to have reasonable counterpoints, and none of them really address the notion of enhancing bad APIs that you’ve been given or putting out your own extensions to preserve reverse compatibility.

So, as an experiment, I developed a little utility and decided to load up on extension methods to really try them out, having previously only been a client of them. I was writing a bunch of things out to an HTML file and using the XDocument API to do it (taking advantage of the fact that HTML is conceptually a subset of XML), so I thought I had the perfect opportunity. I added a bunch of extension methods for XElement that would do things like create tables, styles, and other HTML constructs. I would do something like myXElement.CreateTableOutline(rows, columns, title, headerColor);

It was pretty slick. And, as I did it, I found that these extension methods begat more extension methods for other things. Pretty soon, I had the cleanest, easiest to read code that you could ever want in a data access object. It read like a book, not like code: “Element.CreateTableWithThis()”, and, “Element.PopulateTableWithThat();” Best of all, it looked like a beautiful object-oriented design.

And, at that moment, the thing I couldn’t put my finger on that had been bothering me leaped into full view. It looked like object-oriented design. Extension methods, as I mentioned earlier, are just stateless (hopefully) static methods gussied up to look like instance methods. And, stateless static methods are really just procedural constructs that exist outside of any application state at all–the much younger brother with a striking resemblance to something in the C world that you might call “utils.c” and populate with 8000 functions that just didn’t fit anywhere else.

The whole time, I had been making my code increasingly procedural. I had been moving ugly functionality out of my instances and putting it into the blob of stateless static functionality, prettying it up by making it a series of extension methods. Rather than create some kind of HtmlElement class that inherited from or wrapped an XElement, I created a laundry list of extension methods that could easily have been called “public static class HtmlUtils”. Taken to its logical conclusion, I could write an entirely procedural application with nothing but extensions of existing classes. I realize that nobody is likely to do that, but it is interesting that such a thing is possible and that you can gravitate toward it without realizing it.

And that is the crux of what bothered me all along. Here, we have a brand, spankin’ new language feature introduced to an object-oriented language that gives users the ability to make their code substantially more procedural while making it look substantially more like a clean object-oriented design. Extension methods are the ultimate in deodorant for a code smell. If you venture down that rabbit hole, you’ll never ask yourself why you’re increasingly favoring static utils methods instead of object-oriented design because you will fool everyone else and even yourself into thinking that you are using object-oriented principles.

The denouement of my little story was that I systematically removed all of the extension methods. In their place, I created a series of small methods on a common base class and factored some of the functionality into value objects and small inheritance structures that defined HTML constructs. The result wasn’t as pretty, and I didn’t get the fluent interface feel, but the way I see it, I gave up high fructose corn syrup for fresh-squeezed orange juice. The new design may have required that I add a few classes, but I now have the ability to extend CreateTable() in sub-classes rather than adding a bunch of additional static methods for that functionality. With stateless static methods, you can’t inherit base classes or implement interfaces to take advantage of polymorphism.

I’m not advocating that everybody swear off extension methods (or really advocating much of anything), but rather explaining why I don’t like the construct and choose not to use it. Since my discovery, I’ve paid closer attention to how other people use extension methods. I’ve seen them used to circumvent the compiler for preventing circular dependencies. I’ve seen them used to ‘extend’ functionality in the same namespace where it would have been perfectly reasonable just to add a method to the class itself. I’ve even seen them used to hold and alter global state. And I’ve also seen them used somewhat reasonably.

But, at the end of the day, extension methods are the cousin of the singleton in that they both have an unanticipated side effect. That side effect is a vehicle for developers who are forced to develop in OO languages, but have always carried the torch for procedural programming, to sneak back to visit the ex without anyone knowing. In both cases, for the OO programmer, I would advise a bit of frank examination of the motivations for using the construct. Is it because extending the class (or forcing one global instance) is the only/best possible approach, or is it because it’s easier and faster than taking a hard look at your design or object graph? If it’s the latter, you could be heading for some headaches down the road.

  • http://antisanity.net antisanity

    There is the confusion that one might experience not knowing through intellisense whether you were dealing with a native method of some class or an afterthought that somebody tacked on.

    Visual Studio 2010 intellisense denotes extension methods as such.

  • http://www.daedtech.com Erik

    That’s a nice addition. I had thought that the “(extension)” that you see in intellisense was the result of standard C# libraries having it added to their XML comments, but I just ran an experiment, and this appears to happen automatically for any extension method. That is, I created an extension method with no documentation that takes one of my classes as a parameter and intellisense shows me “(extension)” automatically. Nice catch.

  • http://my4hours.com Rasmus

    “Extension methods are the ultimate in deodorant for a code smell.”
    => Fantastic line :)

    I’ve done a lot of Ruby development as well (a dynamic language) and here you don’t really care about clashes and all the stuff you start out mentioning. That’s really the nature of dynamic languages, but the whole argument about state is dead on!

    We think we’re doing our code more OO, but in fact we should rather look into the “good ol’ inheritance thing”, constructs that lived before all the syntactic sugar the c# compiler gets more and more of.

  • http://www.daedtech.com Erik

    I’m glad you liked it :)

    I poked around a little when I was writing this post to see what other people thought of extension methods and saw Ruby mentioned rather prominently. I hardly have any experience with Ruby, but I do understand the nature of a dynamic language and how that might interact with the extension method construct. I’m glad to see that what I was talking about does seem to transcend languages, and I’m glad that I’m not the only one who sees it and thinks that some caution is in order. I do personally like a lot of things they’re adding to C# as they go, but this one seems a little iffy to me because of how it seems to beg for procedural code in an OO language.

  • Alethia Barnhardt

    Couldnt agree more with that, very attractive article

  • http://www.daedtech.com Erik

    Thanks for the kind words — glad you enjoyed.

  • Verda Keniry

    If you are open to having a guest blog poster please reply and let me know. I will provide you with unique content for your blog, thanks.

  • http://www.daedtech.com Erik

    If you want to send me a link to a technical blog that you write or else send me a bit about your technical background, I’m happy to consider it. The more the merrier.

  • score

    Hi there, I found your blog via Google while searching for a related topic, your site came up, it looks good.

  • flagyl

    Really interesting blog, keep up the good work!

  • Kevrell

    I suppose that sounds and smells just about right.

  • Pingback: Basic Unit Testing with JUnit for C# Developers 2 | DaedTech

  • http://www.facebook.com/skhandewale Sandeep Khandewale

    This is great article. Many thanks Erik for this. I was searching for language comparison and wanted to know what languages are providing features like C#. my observation has always been that C# team finds out architectural patterns being used in industry in version n, and, adds them as feature in version n + 1. I currently have 5+ years of experience in .Net (c#) but I want to master another language. doesnt have to be OO. doesnt have to have LOTS of features (syntatic sugar ;)) but one intelligent enough to allow me create extensible, maintainable, componentized webapps. can you please suggest?

  • http://www.daedtech.com/blog Erik Dietrich

    Glad you liked it, and thanks for the kind words. As for other languages to learn with a web focus, Ruby seems to be all the rage these days, particularly among clean coder types. I don’t know it myself, but if I were going to pick one out to learn right at this moment, I’d probably give it a look.

  • http://www.facebook.com/skhandewale Sandeep Khandewale

    Thanks!

  • EvaO

    Funny how often Ruby is mentioned in the comments considering how Ruby goes far beyond extension methods and even allows you to override methods in classes already defined. Extension methods are mixins with safety scissors (which are in turn multiple inheritance with gloves on). The only commonly used OO language I can think of that doesn’t use extension methods, mixins, or multiple inheritance is Java. There is no dearth of ugly util classes in Java. I have never seen people use extension methods as fancy utils as much as I’ve seen people use util classes as regular ugly utils in Java, so I’m not convinced C# “encourages” procedural programming. I would wager that the folks misusing extension methods would use procedural programming just as much in any language. The difference is in how pretty it looks when they’re done.

  • Danny Miller

    While I am not a big fan of overusing extension methods, I don’t find your reason to be compelling. There are a couple reasons for that.

    1. From day one, I and the other developers around me understood the static utility nature of extension methods and therefore used them with proper moderation.
    2. In object oriented languages like C# and Java, all instance methods are really no more than static methods accepting a first parameter of “this”. Seriously. It is just syntactic sugar that you write them the way you do. After all, every instance of a class does not hold a whole new definition of its functions… rather they are stored in a static class definition and provided the instance as context. So extension methods and instance methods do not differ in basic concept, only slightly in syntax and in where the compiler allows the code to live.

    Again, I don’t use extension methods a whole lot. While they can quickly and easily add powerful and expressive capabilities, I have found more traditional OO approaches to offer what I need.

  • http://www.daedtech.com/blog Erik Dietrich

    It was a few years ago that I made this post, and at the time I was surrounded by people who abused the construct heavily. In the time since then, I’ve come to find it convenient to add extension methods for third party APIs that I find lacking, particularly in test projects. I’ve also offered them as extensions of APIs that I’ve written. So I definitely get (1).

    Your point (2) is confusing to me. I’m talking about syntactic sugar in the sense of one source code construct (extension methods) masking the nature of another (static utils methods). You’re talking referring to the way the compiler implements things as “syntactic sugar” and jumping a level of abstraction. Using this sort of reasoning, I could say that object orientation and even while and for loops don’t matter because it’s all just “syntactic sugar” over assembly instructions and branch/goto. An applications programmer doesn’t care what register the “this” pointer is passed in or how it gets there, but he most certainly does care that there is a language construct that causes static methods to appear at casual inspection to be instance methods. And in terms of application design, there most certainly and unequivocally is a huge difference between static and instance methods (participation in polymorphism, just for starters).

  • Danny Miller

    I agree with you, maybe I was jumping a level of abstraction that most people would not. And there’s no arguing that at the language level there’s a difference between instance and static methods. For being a young guy, though, I often do have that feeling that it is unfortunate that people don’t realize object oriented programming is just a prettier language-supported (or enforced) syntax for what you could already do in non-objected oriented languages. I love OO, live in it every day, and like the extra work the compiler does for us, but I don’t drink the Kool Aid :)

    It’s very relevant that you bring up polymorphism, because while I didn’t list any of my personal top downsides to extension (aka static) methods in the previous comment, the lack of polymorphism would be my #1.

  • http://www.daedtech.com/blog Erik Dietrich

    I looked for it over the weekend, but I couldn’t find the link to something I thought you might enjoy. It was a talk where Bob Martin showed an example of inversion of control using C and pointed out that you didn’t need OOP to have good “OOP design” so to speak — that good design transcends paradigms.

  • Danny Miller

    That would indeed be interesting! I know some big Uncle Bob fans around here :)

  • Pingback: Hiding your dependencies – an expert programmer’s guide | Martin Doms

  • Pingback: Help Yourself To My Handy Extension Methods | DaedTech