Framework Design Guidelines: Extension Methods


Continuing in our weekly blog post series that highlights a few of the new image5_thumb2_thumb2_thumb_thumb_thu_thumb_thumbadditions to the Framework Design Guidelines 2nd edition.. This content is found in the Extension Methods section of Chapter 5: Member Design. One of the major new features we added to the Framework recently is extension methods. While this a very powerful new feature, it does come with some new responsibility.

CONSIDER using extension methods in any of the following scenarios:

  • To provide helper functionality relevant to every implementation of an interface, if said functionality can be written in terms of the core interface. This is because concrete implementations cannot otherwise be assigned to interfaces. For example, the LINQ to Objects operators are implemented as extension methods for all IEnumerable<T> types. Thus, any IEnumerable<> implementation is automatically LINQ-enabled.
  • When an instance method would introduce a dependency on some type, but such a dependency would break dependency management rules. For example, a dependency from String to System.Uri is probably not desirable, and so String.ToUri() instance method returning System.Uri would be the wrong design from a dependency management perspective. A static extension method Uri.ToUri(this string str) returning System.Uri would be a much better design.

RICO MARIANI

The value of this cannot be overstated. Extension methods provide you with a way to give interfaces not just one default implementation but as many as you need, and you can choose between them simply by bringing the right namespace(s) into your lexical scope with using. However, this could be easily abused in the same way that complex #include combinations in C++ can make the final code hard to read.

Another interesting feature of this manner of adding functionality to a class is that you could potentially partition (extension) methods of the same class into different assemblies for performance reasons. Again, this should not be done lightly, because you could cause great confusion.

This is one of the many times I like to quote from Spiderman – “With great power comes great responsibility.”

PHIL HAACK

Section 2.2.4.1 covers the topic of layering in namespaces, which I think applies well to extension methods.

One scenario I’ve seen is to put functionality that is more advanced or esoteric in a separate namespace. That way, for core scenarios, these extra methods do not “pollute” the API. But for those who know about the namespace, or need these alternate scenarios, they can add the namespace and gain access to these extra methods.

The drawback, of course, is that this results in a “hidden” API that is not very discoverable.

JOE DUFFY

Extension methods can also be used to provide actual concrete method implementations for interfaces. For example, if you ship an IFoo interface, you can also have a static Foo class with a method public static void Bar(this IFoo f) that makes all instances of IFoo effectively have an extra Bar method.

Comments (10)

  1. Extension methods are just great, making code more readable and understandable.

    I’m missing static extension methods (define a static method on a class or interface). Are there any plans to include that at some point?

  2. Andrei Rinea says:

    Along with static extension methods a nice addition would be extension properties.. In fact they’re still methods behind the scene, right?

  3. David Nelson says:

    Hopefully, the actual entry in the book spells out the disadvantages of extension methods more strongly:

    – They are not discoverable. You can’t just look at intellisense or the class documentation to discover its capabilities. You have to have foreknowledge that the functionality you want exists and what namespace to find it in.

    – The are fragile. Extension methods introduce a new version of the Fragile Base Class problem, where an instance method introduced in a later version of a class will silently and transparently replace the extension method. For some reason, no steps were taken to mitigate this problem in the design of extension methods.

  4. @ Head says:

    A comment by Joe Duffy on the Framework Guidelines for Extension says : Extension methods can also be

  5. VB Feeds says:

    A comment by Joe Duffy on the Framework Guidelines for Extension says : Extension methods can also be

  6. Dave says:

    Personally I find that extension methods clobber the code. People who are unfamiliar with the extensions used might be confused that SqlCommand suddenly had an SetErrorCallback.

    cmd.SetErrorCallback( (e) => Console.WriteLine(e.Message));

    Might seem out of place in stead of

    SqlCommandUtil.SetErrorCallback(cmd, (e) => Console.WriteLine(e.Message))

    in your code  what would be used by the compiler eventually.

    I haven’t found one usefull usage of extention methods.

  7. I’m spending some time this morning getting caught up on RSS reading.&#160; A great post from last week

  8. I&#39;m spending some time this morning getting caught up on RSS reading.&#160; A great post from last

  9. I agree with Andrei!  Extension properties might be awesome, the other day I was really wishing I could make a TimeSpan.OneDay extension property.

    Also, I  actually favor keeping my extensions somewhat hidden.  The extensions I use on one project aren’t necessarily always applicable in another.

  10. Kevin Westhead says:

    As David points out, there are disadvantages to extension methods but the full text does cover them. However I’m not convinced about the concerns with discoverability. Extension methods are typically used in scenarios where static methods on helper classes would have been used before. With extension methods you need to know the namespace but with static helpers you need to know the class name. This might not be obvious if you’re dealing with more derived types. Both approaches have problems but I’ve frequently found that extension methods naturally end up in a commonly imported namespace, which means IntelliSense is usually available for all compatible types. Nonetheless, as others have already said and as the full FDG text states, extension methods shouldn’t be used frivolously.