views:

153

answers:

5

Before you start pointing me to duplicates just know that I have read nearly all the posts on SO about extension methods. I am just trying to play devil's advocate for a minute to consider the alternative to my working opinion.

Recently I was working on a project and a need came up for a method to be a base of an interface. So I suggested we write an extension method and it was shot down. Saying it added complexity and harder to debug.

I of course argued and got on SO to find all the wonderful posts that show the many reasons why to use extension methods. Not to forget that a lot of the .net framework uses them. We eventually did not use it as I was overruled by the team.

But then it got me thinking, are there times when an extension method could be used but shouldn't be?

I really couldn't think of any but thought I would post here and see if anyone could think of any other reasons why they shouldn't be used.

A: 

I would say you should avoid them when "they do not make the intend of the code more clear". Of course, whether or not some code (or codeing style) is "more clear" varying widely between people, so that's pretty much useless. (I had one boss who said we shoudl avoid using interfaces because they made the code "too complex and hard to understand")

James Curran
I just wonder how you could ever have a situation where it could be bad. I guess if you were putting methods that had nothing to do with the class, or interface, itself as an extension method that would be one of those situations.p.s. Your boss sounds like a real OOP master :P
spinon
+1  A: 

In general if you control the source-code for the assembly and adding the method does not cause any breaking changes to existing code (which would have been the case if for example LINQ had not been implemented via extension methods) it is better to just add a normal method.

kekekela
+1  A: 

This discussion of the Framework Design Guildelines section on extension methods contains some good advice. I think the relevant portion for your scenario is:

To provide helper functionality relevant to every implementation of an interface, if said functionality can be written in terms of the core interface.

If your proposed usage did not pass that test then it should have been shot down.

Jamie Ide
I will see if I can dig up the scenario and post a modified explanation here.
spinon
+5  A: 

Any time you have a function which is "generally applicable" to an object of a certain type, regardless of its state, an extension method is a good choice.

For example, today I added two new extension methods to our codebase:

public static XElement ToXElement(this XmlElement element) { }

public static XmlElement ToXmlElement(this XElement element) { }

Both of these are, generally speaking, valid on the types they extend regardless of the state of the instance or where we are using it.

If your method does not meet that criteria, it should probably be moved to a helper method closer to the context where the particular case is always true or easily checked.

For example, a developer recently nominated this to be an extension method:

public static bool ParseYesNoBool(this string input) { }

There are two problems here: first, this will appear on all strings in the application, even though the number of strings which might ever be candidates for this case are very small. So we've broken the first rule, in that it is not useful regardless of state. Similarly, but second, the consumer of this functionality is limited to a single parser for one particular connector to an external system. So promoting implementation-specific functionality into the general-use namespace makes no sense. This was downgraded to a helper method in the parser.

As far as readability and debugging, that is just incorrect for a developer of any reasonable skill level.

Rex M
I worked with someone who had a huge file of extension just for object, most being rather specific. I almost had to start taking anger management classes...
ChaosPandion
@anon why the DV?
Rex M
These are both two great examples of when they should and shouldn't be used. I have seen similar situations where object specific functionality was added to clr objects. They were checking for domain object specific rules in the type and wanted to just add extension methods to the type to make it easier.I think I have another question for SO that I will post rather than try to fit it all in this comment? Plus make it searchable for future reference.
spinon
So I skipped the question and will just ask here in another comment:Would it be bad to promote your ParseYesNoBool to an extension method if that logic was only ever used within the context of a few namespaces? That doesn't sound right.Basically, wondering what if you had domain specific extension methods for a specific type. They would only be used if you loaded the namespace that contained the extension method so it wouldn't be available to all uses of string. Just those specific to that realm of use.Following?That's why I didn't write another question. I couldn't word it right?
spinon
I feel like yes it would be because that would introduce unnecessary complexity but at the same time would add better readability to your code. Just felt like I needed a second opinion.
spinon
if you are using namespaces properly, all extension methods shouldn't be available everywhere. I have no problem with context specific extensions that are only there in the context they relate to.
Matt Briggs
@Spinon @Matt that is true about namespaces. I am in a slightly different boat as I have to manage both a framework and consumers of that framework, and sometimes a little in between, and in the framework-y cases we try to keep our namespaces pretty flat.
Rex M
A: 

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type.

Any time you break the intent and design for the feature I would recommend reconsidering the use of an extension method. I see a few situations when you don't want to use an Extension method:

1) Changing the Object Model to allow for an Extension method: The class you want to create an extension on is an abstract class. This is going to require you either make each inherited class it's own version of the extension or remove abstract from the class. Either way, you are changing the object model in order to use an extension method.

2) Forgetting the Decorator Pattern: The number of extension methods you create for a class exceeds three. I find it is easier to organize/communicate and maintain the domain/object model with decorated objects than with extended objects. However, the opposite is also true: If a decorated object has less than four methods, I find a lot of almost "empty" objects in my project.

3) Private functions: Private functions are meant to modify(create, delete, etc..) the object and extension methods are meant to use the type, much like a struct would. If you find the extension is being assigned to another instance of the type then it probably should not be in an extension.

Lucas B