C# has had extension methods since 2007 and with it came LINQ (Language INtegrated Query) and a massive set of extension methods that changed C# development forever. It is a prime candidate for demonstrating the power of extension methods and it did its job very well.

I love extension methods and utilize them both as a consumer of other extension methods and as a developer of my own. Recently, I got the opportunity to rearchitect the backend of our application at work. The application is data intensive and has about 800 tables in it. It is huge and still growing. In the process of developing the architecture, Michael and I would have discussions about how to implement different parts of the system. Sometimes it would be an extension method and sometimes it wouldn't be and sometimes we would go back and switch from one to the other. There were a few instances of both directions so it wasn't a clear line.

These are the issues that I have found with extension methods:

  1. Discoverability: if you don't know it exists you can't use it. Which leads to code duplication.
  2. Separation of Concerns: If you put a deserialize method on string, all instances of string have that method and it appears that string implemented it. Making it appear that string is breaking a separation of concerns. Also most of the time the class holding the extension method is breaking separation of concerns anyways because it is doing multiple things.
  3. They're static: Since they are static classes you can't utilize Inversion Of Control principals (dependency injection) and other techniques as easily in order to change their behavior.

Checklist for whether you should be using an extension method:

  1. Maintains perceived separation of concerns.
  2. Can you change the code.
  3. Interfaces with multiple implementations

If you are going to break separation of concerns do not create an extension method, create a separate class.

If you can modify the code without undue hardship, then just add the method to the class.

If you have an interface with multiple implementations and it doesn't break separation of concerns, then an extension method is likely the way to go, even if you own the code. Otherwise you would have to duplicate the code.