Yesterday I had a discussion with a co-worker about extension methods, he was concerned with some of the extension methods I was using and emailed this guidance when to NOT use an extension method:
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.
I was confused because I read that guidance and I think that is a perfect time to use an extension method. I asked where he got the guidance and he set me the following links:
- Brad Abrams: Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries
- http://blogs.msdn.com/brada/archive/2009/01/12/framework-design-guidelines-extension-methods.aspx
If you look at the second link you see that in fact the guidance is FOR when to use extension methods. So apparently there was just a miscommunication on what the guidance was saying.
Here is my feeble attempt at explaining what the guidance is saying.
All the code can be found in my Learning GitHub Repository and the Learning CSharp solution @ http://github.com/RookieOne/Learning
Suppose we have a class Foo. And with Foo we have a method ‘Whatever’ that returns a type Bar. Normally we would do something like this:
1 2 3 4 5 6 7 |
|
By writing our method this way, we make the BadFoo class dependent on the Bar namespace / assembly. When someone uses a BadFoo class they get to see the Whatever method and not realize they are going to also be dependent on the Bar namespace / assembly.
Instead of writing the Whatever method as an instance method, we can write the method as an extension.
1 2 3 4 5 6 7 |
|
I now can see that the Whatever method is clearly an extension method off of Foo. And yes, if I use the method I will then need the Bar namespace / assembly, etc. The difference is that with an extension method it is more of an opt in scenario. I can have users of Foo that don’t need the Bar assembly nor the Whatever method.
This is sort of hard to explain but I am giving it my best shot. :) Maybe some whiteboarding will help.
Without the extension method, the Foo.dll has to reference the Bar.dll. If we instead moved the Whatever method out into an extension method in the X.dll we can see that Foo.dll no longer needs to reference the Bar.dll.
Anyway, I like extension methods and think there is a lot of misconceptions surrounding when and how to use them. I think a more interesting topic for extension methods is limiting their scope in order to provide bounded context specific operations. This ‘removing of dependencies’ aspect is just part of that topic.
Again check out some of the code in my Learning solution http://github.com/RookieOne/Learning