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

  • Anonymous
    January 12, 2009
    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?

  • Anonymous
    January 13, 2009
    Along with static extension methods a nice addition would be extension properties.. In fact they're still methods behind the scene, right?

  • Anonymous
    January 13, 2009
    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.
  • Anonymous
    January 14, 2009
    A comment by Joe Duffy on the Framework Guidelines for Extension says : Extension methods can also be

  • Anonymous
    January 14, 2009
    A comment by Joe Duffy on the Framework Guidelines for Extension says : Extension methods can also be

  • Anonymous
    January 15, 2009
    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.

  • Anonymous
    January 20, 2009
    I'm spending some time this morning getting caught up on RSS reading.&#160; A great post from last week

  • Anonymous
    January 20, 2009
    I&#39;m spending some time this morning getting caught up on RSS reading.&#160; A great post from last

  • Anonymous
    January 20, 2009
    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.

  • Anonymous
    January 21, 2009
    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.