views:

409

answers:

5

I've been using extension methods quite a bit recently and have found a lot of uses for them. The only problem I have is remembering where they are and what namespace to use in order to get the extension methods.

However, I recently had a thought of writing the extension methods in the System namespace, System.Collections namespace or some other system namespace that makes sense. So for example, I've implemented the following.

namespace System
{
    /// <summary>Various array extensions</summary>
    public static class ArrayExtensions
    {
        /// <summary>Converts the array to a hex string</summary>
        /// <param name="value">The value.</param>
        /// <returns>The array as a hex string</returns>
        public static string ToHexString(this byte[] value)
        {
            var hex = new StringBuilder(value.Length * 2);
            foreach (byte b in value)
            {
                hex.AppendFormat("{0:X2}", b);
            }
            return hex.ToString();
        }
    }
}

Is this the correct thing to do?

+8  A: 

You should avoid augmenting namespaces over which you do not have primary control as future changes can break your code (by introducing duplicates, for example).

I tend to mimic the standard namespaces with a different root namespace that identifies all child namespaces as belonging to my work. The root namespace could be your name, your organisation's name, or something else that identifies the contents of that namespace as being yours.

For example, if you want to extend System.Collections, you could use NickR.Collections or NickR.System.Collections.

Jeff Yates
+2  A: 

Not sure if it's wrong (or right, for that matter), but why not have your own 'Extensions' namespace? Then put all your extension methods in that namespace and be consistent about it.

I don't think the real problem is where to put them or what to name it (system or any other namespace), but to be consistent and always use the same to avoid your problem (forgetting where they are).

Ricardo Villamil
+12  A: 

From the Framework Design Guidelines (2nd Edition):

DO NOT put extension methods in the same namespace as the extended type, unless it is for adding methods to interfaces, or for dependency management.

While this doesn't explicitly cover your scenario, you should generally avoid extending a Framework namespace (or any namespace you have no control over) and opt instead to put those extensions in their own namespace. If you feel strongly about "grouping" the extensions (such that the collection extensions are together, etc.) then you could introduce a subnamespace. In your scenario, extension to the collections would go in a System.Collection.Extensions namespace or a Company.Collections or even a Company.Collections.Extension namespace.

In order to use extension methods the namespace containing the sponsor class (the class that defines the extension methods) must be imported. If you add extension methods to one of the standard .NET Framework namespaces they will always (and implicitly) be available.

Scott Dorman
A: 

I put my extention methods in a namespace depending on the visibility I want them to have. That way they are easier to discover, and I usually get fewer namespace imports.

Thomas Eyde
A: 

The only thing that the namespace really affects with extension methods is visibility and discoverability - so it depends on whether you want the extension methods to always appear on that type or not. The framework design guidelines are intended primarily for public APIs and so, while it's generally a good idea to follow them, the rules are very much there to be broken for internal APIs when it makes sense.

For example, we do a lot of work with TimeSpan objects throughout the codebase and there are no methods to multiply or divide these in the framework so we have added MultiplyBy and DivideBy extension methods, amongst others, and put them in the System namespace because we want them accessible and discoverable wherever a TimeSpan is used.

On the other hand we also do quite a bit of reflection work, operating on Type objects, and there are a whole lot of extension methods that are very useful in specific areas but not generally, so these live in a OurCompany.Reflection namespace so they have to be specifically imported.

So for internal APIs the decision boils down to "do I want this method to be available everywhere the type is available in our codebase?". If the answer is yes, then put it in the same namespace, otherwise put it somewhere else.

Greg Beech