DaedTech

Stories about Software

By

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.

By the way, if you liked this post and you're new here, check out this page as a good place to start for more content that you might enjoy.
46 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
antisanity
12 years ago

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.

Rasmus
12 years ago

“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.

Kevrell
Kevrell
12 years ago
Reply to  Rasmus

I suppose that sounds and smells just about right.

Alethia Barnhardt
Alethia Barnhardt
12 years ago

Couldnt agree more with that, very attractive article

Verda Keniry
Verda Keniry
12 years ago

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.

score
score
12 years ago

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

flagyl
flagyl
12 years ago

Really interesting blog, keep up the good work!

trackback

[…] type or being a child class of the class containing the static method. This feels icky to me, like C# extension methods, but I’m grudgingly using it for now with my tests and assert (I may revert to traditional […]

Sandeep Khandewale
11 years ago

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… Read more »

Erik Dietrich
11 years ago

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.

Sandeep Khandewale
11 years ago
Reply to  Erik Dietrich

Thanks!

EvaO
EvaO
11 years ago

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… Read more »

Danny Miller
Danny Miller
10 years ago

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… Read more »

Erik Dietrich
10 years ago
Reply to  Danny Miller

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… Read more »

Danny Miller
Danny Miller
10 years ago
Reply to  Erik Dietrich

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… Read more »

Erik Dietrich
10 years ago
Reply to  Danny Miller

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
Danny Miller
10 years ago
Reply to  Erik Dietrich

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

trackback

[…] Extension methods are an oft-overlooked way of hiding dependencies from the user. Remember, callers of our code should have no idea what we depend on – that’s an ugly, messy implementation detail. Which is why when the caller sees this: […]

trackback

[…] nothing like 3 years (or almost 3 years) of elapsed time to change your view on something, such as my take on C# extension methods. At the time I was writing this post, I was surrounded by wanton abuse of the construct, […]

bingbingwa
bingbingwa
9 years ago

Just finished a c# book where extensions were crucial to some of the design patterns. You do use design patters, don’t you?

Erik Dietrich
9 years ago
Reply to  bingbingwa

I’m not really sure I understand the motivation for the question about whether I use design patterns or not. I mean, it’s hard to infer tone from text, but this comes off as, “I saw someone use extension methods as part of the implementation of a design pattern, so if you don’t use extension methods, you must not use design patterns.” This is a pretty hard sell, given that the Gang of Four design patterns and presentation layer standards like MV* predate the release of extension methods and, in some cases, even C#. (Assuming that’s what you meant and that… Read more »

bingbingwa
bingbingwa
9 years ago
Reply to  Erik Dietrich

using static methods rather than extension methods… sounds like a good topic to write about next. I’d like to learn more about this.

Erik Dietrich
9 years ago
Reply to  bingbingwa

I can certainly write up my take on the subject. I’ll put a placeholder in my drafts folder and write a bit about it when I get a chance (and respond again to this comment when I do).

bingbingwa
bingbingwa
9 years ago
Reply to  Erik Dietrich

Sounds good!

Anthony Ruffino
9 years ago

Hi Erik, I have a good use case for extension methods: On any object that has access to the application cache in an MVC application. The cache is dynamic and it can soften some of the overly sweet syntactic sugar that is at the static of extension methods. I have been using extension methods in a C# Class library that I intend to share with some developers at the office. The main idea for the library is that it contains a IWebAppManager interface which specifies some core functionality that is meant to be implemented by a concrete class. Of course… Read more »

Erik Dietrich
9 years ago

When I wrote that post, the language feature was pretty new and people were using it to do all manner of horrifying things in the code base I was working with at the time. That certainly colored my take back then (and really, I think there’s a period of “I can so I will” with any new language feature). It’s not hard for me to imagine that people will find use cases for the feature that make code simpler or more readable. As for performance gains, I tend to gravitate toward making things as readable as possible until such time… Read more »

vishok
vishok
8 years ago
zak willis
zak willis
8 years ago

This is a worthy article, and some valid points. If your entire codebase is filled with hundreds of extension methods then you have a point. However, Extension methods could be considered a helpful tool in the evolutionary life cycle of TDD/conceptual before understanding what the application is supposed to do and then moving these static helpers into a class that gives it context – which is what you did. So right now, I am writing a class to manage saving data from a POCO (more complex than that). So I started by encapsulating any helperesque functionality inside that class, it… Read more »

Realtebo ✔ᵛᵉʳᶦᶠᶦᵉᵈ
Realtebo ✔ᵛᵉʳᶦᶠᶦᵉᵈ
8 years ago

100% ok
Or I extend Or I create a static util class, both I want to avoid to create something as a static utils than lokks like an extended class (or viceversa. … )

sm
sm
8 years ago

Nice.
http//www.codingsack.com

Panos Roditakis
Panos Roditakis
7 years ago

Extension methods are dangerous when developers implement business logic inside them.
For example I was extending NopCommerce the other day and wanted to override the cart.RequiresShipping() method. When I tried to do so without changing their core code (.cs file), I was disappointed to see that it was an extension method used in 20 different places and the override would remain a dream.

So, once again, it’s not the tools fault, but the way they are used.

Erik Dietrich
7 years ago

In the years between writing this and now, my view has become more nuanced, but what you’re describing, business logic in extension methods… yikes. I still would most certainly not be a fan of that.

Ronak Thakkar
Ronak Thakkar
7 years ago

Extension methods are just syntatic sugar on static methods and they are bound at compile time and not based on instance type on run time. It cannot be over-ridden and does not support polymorphic scenario. This can create big problems. I created some extension methods as they were easy but after some time I realized that I had to override them with another implementation which is not possible. Hence I have to remove all extension methods. Hence as a general principle always create your software that can be extended and Extension methods will block that. So I would never dare… Read more »

steve
steve
7 years ago

I don’t agree completely. Extension methods are not the same as a built-in public or internal class methods but pretty close. C# is about productivity. When you use a class, you often have to interact with other classes which the first class knows nothing about. Your choices are to use an extension method in a comfortable namespace or write another class to encapsulate how those two classes interact. static bool ResultOfEncounter( this ClassA agent this ClassB provocateur) { // special knowledge of both of these classes and how they might interact. } Ultimately a better implementation might be some other… Read more »

Jared Barneck
7 years ago

I wouldn’t say, “I don’t like extension methods” because you probably use them all the time and love the ones you use, even if you don’t know you are using them. For example, you can’t love LINQ without loving extension methods. Extension methods were developed with a purpose. When used for that purpose, extension methods are phenomenally power tools to enhance any C# project. However, you have a point, that like any tool, it can be used incorrectly. Many of the uses you have mentioned may or may not be good purposes. Purpose 1: Adding methods to sealed classes. There… Read more »

Aluan Haddad
Aluan Haddad
7 years ago

I realize from reading the comments and responses that your views have evolved over the years, however I think you are missing a few fundamental points. 1. You seem to be under the impression that C# is an object oriented language. C# like most programming languages is a multi-paradigm language. It favors a number of Object Oriented techniques but it also has higher order functions, generics, and a myriad of procedural constructs and lots of other things that are not Object Oriented. If you have ever been told that C#, C++, or even Java “is an Object Oriented Programming language”,… Read more »

RenniePet
RenniePet
7 years ago

I love your writing style. If you ever get tired of programming you should become an author.

Erik Dietrich
7 years ago
Reply to  RenniePet

Thanks! That means a lot. And, for what it’s worth, that’s kinda the plan. If you visit the site again, check out the sidebar at the right to see the book I’m writing — Developer Hegemony. After we publish that, I’m contemplating a foray into fiction.

Michiel Huygen
Michiel Huygen
7 years ago

You describe that use of extension methods makes your code more procedural and less object-oriented. Did you consider the fact that extension methods can also be seen as a way to introduce Functional programming concepts into C#. If you look at the LINQ or Reactive extensions libraries, extension methods are mainly used to achieve a combination of functional programming and object oriented programming that i rarely see in other languages.

I therefore think that use of extension methods in itself is not a code smell, but using them to do procedural programming is. What do you think about this?

cyrille
cyrille
7 years ago

Thank you for your article even if I’ll keep using the extensions methods exactly because you can have a fake turn-around a big limitation of C# : the single inheritance. By adding extensions methods to interfaces, generic ones if possible, you can reach an aspect-oriented design, where adding an interface gives your objects some pre-determined behaviour. Mainly, it attaches the tools that you usually need where you use them, without reinventing the wheel anytime you change the implementation, helping with maintaining the code. It is not as powerful as a real multiple inheritance, but it helps. It obviously comes with… Read more »

Brady Kelly
Brady Kelly
6 years ago

You horribly abused extension methods so they’re bad and you don’t like them. Fine.