views:

332

answers:

7

Right, so MS introduces Extension Methods for C# 3.0. Basically, it allows you to add new methods to an existing classes without having to subclass from it or change its implementation. Immediately alarm bells go off in my mind.

1) You start implementing your own extension methods for a library or standard library classes. Now it is not standardized anymore.

2) In OOP, you define a new type either through inheritance or composition. What actually is extension methods then? Likewise, in using extension methods there is no explicit relationship defined.

3) Are extension methods portable between projects? What if two extension methods for a method exists?

So are extension methods a whole bunch of worms worth avoiding? I can see that there are merits in it, as in you type less, but somehow it looks like would lead to bad practice.

Opinions?

+9  A: 

Extension methods are not added to a type. They are just syntactic sugar. You can't access private stuff. An extension method is just like any static method that consumes a type.

Worst thing they can do is to harm readability and mislead people. Beyond the syntax, they are nonexistent.

UPDATE (re comment):

This is exactly what I meant from "misleading people" and "harming readability." Fortunately, Visual Studio is pretty helpful in distinguishing extension methods (using an icon in the IntelliSense list and the tooltip). Personally, I'm a little biased against adding a bunch of extension methods to arbitrary classes of the framework (with the exception of sealed classes where extension methods can make a lot of sense) unless they provide a significant benefit for the particular project. I prefer keeping extension methods mostly for interfaces and classes on top levels of inheritance hierarchy. This will make developers only use them where they are applicable to many cases in the framework rather than making any utility method an extension (IMO, this is direct artifact of autodiscovery of extension methods in a whole namespace. I really wish C# required you to add a using directive on a the specific class rather than automatically importing all extensions in a namespace).

In my experience, if you don't overuse extension methods by making every utility method that's used a few times (I've seen some people do this) an extension, it's rarely a maintenance problem. It will improve readability if used wisely.

Cluttering up classes with extension methods is not a good thing. At the extreme cases, it can be dangerous. One might introduce a name collision issue by adding a method to class with the same name of an already existing extension. This can break code snippets that previously called the extension and are now calling the new method.
In my opinion, this is the biggest issue associated to extension methods. This makes good naming of extensions very important.

Mehrdad Afshari
Thanks for the explanation. Just wish to ask, in your experience, how would extension methods impact code sharing or handing over of projects to a new a team. Say I add a "wordcount()" to string - is it apparent that is an extension method, and not an actual method of string? How does this work out for maintaining of code?
Extrakun
+4  A: 

No, it's not a can of worms worth avoiding. It can make life a lot simpler, and IMO it allows you to separate out the core operations of the type from "helper" methods which can be implemented solely from those core operations. I've been tempted to use extensions methods in that way even when they're not really necessary (i.e. I've had a base class to put them in, and I'm in control of the code).

You need to understand that extension methods are just a way of making static method calls look like instance methods, when the appropriate namespace containing the extension methods is imported. In particular:

  • It doesn't add methods to a type, so it's not making standard libraries "non-standard". It just means that if you've got the extension methods available, you may be able to work with those libraries more easily.
  • There is an explicit relationship defined with extension methods: the extension method declares which type it is "extending" with the type of the first parameter. It's not composition or aggregation, but I don't see why that's a problem. If something is useful and doesn't actually make the design worse, does it matter whether it's part of traditional OO?
  • Yes, extension methods are portable between projects. As always, there are rules for what happens if two extension methods with the same name are visible at the same time.

Extension methods over interfaces are very nice, allowing simple method chaining etc. I would far rather see an extension method call than an explicit static call as in Java:

// Explicit helper method call
Collections.sort(collection);
// With extensions, this could be:
collection.sort();

A few downsides though:

  • It doesn't allow derived types to override the implementation in a more efficient way. Of course the derived type can declare a method with the same signature, but that'll only get used if the compile-time type is appropriate.
  • The way that extension methods are discovered in C# is a pain. I've ranted about this elsewhere...
  • Extension methods aren't available when using dynamic typing.

Overall though, I think they're lovely - and when used in moderation, they can make all the difference. I certainly wouldn't want to use LINQ without them.

Jon Skeet
Jon, where can i find your rant on extenstion method discovery?
Rohan West
Will see if I can dig it up. There's some info here: http://msmvps.com/blogs/jon_skeet/archive/2008/02/10/c-4-part-4-my-manifesto-and-wishlist.aspx - but I'll see if I've got any more.
Jon Skeet
A very old post here: http://msmvps.com/blogs/jon_skeet/archive/2005/09/28/68147.aspx Basically the problem is it's very broad - you get everything from a whole namespace, even if you only want one type. This means that if you want to create various different extension methods to different types, you ought to consider splitting them into different namespaces *just to give more control to the user*. That leads to far more namespaces than you'd normally want, often with only one or two types in.
Jon Skeet
Thanks Jon, much appreciated :)
Rohan West
+5  A: 

Extension methods do not modify the existing class at all, they are just "syntactic sugar" or a compiler trick for attaching a static method to a class. You can accomplish the same end by just creating a normal static utility method in another class that takes the desired class as the first argument to the method. I see your point about "adding" methods to a class and thereby de-standardizing it, but this is not really what's happening, and I actually find extension methods to be intuitive and convenient for adding domain-specific or utility methods to an existing class that would otherwise be unmodifiable.

Andy White
My thoughts are: for the usual 'wrapper static class', you know that there's another entity involved. Will that be apparent when using extension methods?
Extrakun
+5  A: 

You can switch the alarm bells off. Extension methods make only a very tiny difference to the syntax, and nothing else. Instead of writing:

SomeClass.SomeStaticMethod(someVar, someArg);

You write:

someVar.SomeStaticMethod(someArg);

It simply swaps the ordering and eliminates the class name qualifier. Otherwise, it's identical. The value of this is that you can type a variable name and the IDE can suggest useful methods to you in the intellisense feature, and you can read the code from left to right, so "nested" function calls become far more readable.

All your concerns apply equally to static methods - and are not therefore worth worrying about.

Update

Do extension methods "pretend to do magic"? Only if you think swapping some syntax around is magic!

It's more likely that you are just accustomed to seeing things written in a certain way, and so it comes as a surprise to you to see them written "backwards". But from the perspective of other languages, now it's the right way around.

Some languages allow any non-instance method to be optionally written with the first argument before the method name, and if you leave out the dot then it's a neat way of supporting infix operators like a + b without having to do anything special.

An instance method is one way to enable this syntax, but if you were happy to do without it, then to be truly consistent, why not require instance methods to be called like this?

trimmed = string.Trim(str);

This is similar to how F# does it. After all, an instance method of string can be viewed as having a first parameter of type string. You don't normally think of it as a parameter, but it works much the same, and there are advantages to uniform syntax.

An instance method has access to the private members of the class it is defined in, whereas an extension method does not. But then, an instance method in a derived class does not have access to the private data of the base class. And in any case, why should the caller care about this?

Caveats

I wouldn't want to give the impression that all uses of extension methods make sense. For example, are there any good reasons to make an extension method on object, or a generic extension method on the unconstrained type T? Such things would be suggested by intellisense in almost any context, and would become something like language extensions, e.g. With.

Then there's the debate over whether an extension method should allow its first argument to be null. Personally I think it's fine as long as the method's name makes this clear, so I think string.IsNullOrEmpty would be fine as an extension method. But others are more militant about it, and I don't care, so I'd take a "when in Rome" attitude. Here's another example:

public static void DisposeIfNotNull(this IDisposable d)
{
    if (d != null)
        d.Dispose();
}

The name makes it clear that it incorporates a null check (that's the whole point of it).

Daniel Earwicker
It's strange that the latter is considered syntactic sugar for the former. The former looks much sweeter to me, because it's clear, it says what's going on and it doesn't pretend to do any magic.
Daniel Daranas
I'm just curious what you think: I really like using an extension method that defines "In" so I can use any object, tag a '.In(<parameter list or IEnumerable>)' onto the end of it and test for membership. It feels like a missing language feature to me. Would you consider that an abuse of extension methods?
Cpfohl
+1  A: 

I wanted to raise a bit of an issue with a point you said. Extension methods do not allow you to add methods to an existing class. They allow you to give the appearance of adding a method to an existing class. The distinction is subtle but very significant.

Now to go against the points you made

  1. I don't believe this is true. Nothing has changed about the standarization of the library. People using your extension methods will see an augmentation to the library. Whether or not it changes the standard of the library is highly dependent on what you do in your methods.

  2. It's simply a way of augmenting a type with methods without changing it's original contract.

  3. I'm not sure what you mean by portable but it's likely highly dependent on your implementation. If two extension methods exist with the same name they will go through overload resolution and errors will be raised appropriately.

Using and defining extension methods are simply syntactic sugar for static methods. It allows me to customize a type for lack of a better word with methods that are specific to my problem domain or are simply something that is otherwise missing from the original framework (IEnumerable<T>.ForEach for example).

I don't find any argument of their evilness to be compelling and hence I will keep using them because I find them productive.

JaredPar
+2  A: 

I look at it as a convenient way to implement the decorator pattern. Extension methods let you extend a type by adding methods to it. Of course they are portable between projects if you have your extension classes in a separate assembly which you can share.

mqbt
+1  A: 

Others have already pointed out the fact, that extension methods do not change the original type, so just to add a bit: Keep in mind that the extension methods are only visible once you import the defining namespace. So if you "add" some methods to string, they only become available when you explicitly request these. In other words the scope of extension methods can be controlled. Maybe not perfectly, but at least they don't just appear out of nowhere when someone adds them to a project.

Brian Rasmussen
Thanks, this answer some of the question stated in my comments of above.
Extrakun

related questions