views:

4463

answers:

5

I have been running StyleCop over some C# code and it keeps reporting that my using statements should be inside the namespace.

Is there a technical reason for putting the using statements inside instead of outside the namespace?

Edit: There appears that there is no difference after compliation. The reasons for putting them inside the namespace go against the convention of one class per file (my preferred method, no doubt most people also). Thanks for the good answers.

+52  A: 

Putting it inside the namespaces makes the declarations local to that namespace for the file (in case you have multiple namespaces in the file) but if you only have one namespace per file then it doesn't make a difference whether they go outside or inside the namespace.

using ThisNamespace.IsImported.InAllNamespaces.Here;

namespace Namespace1
 { using ThisNamespace.IsImported.InNamespace1.AndNamespace2;

   namespace Namespace2
    { using ThisNamespace.IsImported.InJustNamespace2;
    }       
 }

namespace Namespace3
 { using ThisNamespace.IsImported.InJustNamespace3;
 }
Mark Cidade
+20  A: 

Here is some information.. My style is to put them outside the namespaces.

http://www.hanselman.com/blog/BackToBasicsDoNamespaceUsingDirectivesAffectAssemblyLoading.aspx

Quintin Robinson
Damnit, I was going to post that link :P
Slace
lol, I could imagine.. it's a good read.
Quintin Robinson
+93  A: 
Charlie
good explanation :)
This is imho a much better reason to put using statements locally than Mark's multiple-namespaces-in-one-file argument. Especially sine the compile can and will complain about the naming clash (see the StyleCop documentation for this rule (e.g. as posted by Jared)).
David Schmitt
Excellent and concise explaination. This should really be marked as the answer.
peteski22
+1 for the great response!
Sayed Ibrahim Hashimi
+4  A: 

Sometimes it makes difference where you put usings: http://stackoverflow.com/questions/292535/linq-to-sql-designer-bug

gius
+4  A: 

According the to StyleCop Documentation:

SA1200: UsingDirectivesMustBePlacedWithinNamespace

Cause A C# using directive is placed outside of a namespace element.

Rule Description A violation of this rule occurs when a using directive or a using-alias directive is placed outside of a namespace element, unless the file does not contain any namespace elements.

For example, the following code would result in two violations of this rule.

using System;
using Guid = System.Guid;

namespace Microsoft.Sample
{
    public class Program
    {
    }
}

The following code, however, would not result in any violations of this rule:

namespace Microsoft.Sample
{
    using System;
    using Guid = System.Guid;

    public class Program
    {
    }
}

This code will compile cleanly, without any compiler errors. However, it is unclear which version of the Guid type is being allocated. If the using directive is moved inside of the namespace, as shown below, a compiler error will occur:

namespace Microsoft.Sample
{
    using Guid = System.Guid;
    public class Guid
    {
        public Guid(string s)
        {
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            Guid g = new Guid("hello");
        }
    }
}

The code fails on the following compiler error, found on the line containing Guid g = new Guid("hello");

CS0576: Namespace 'Microsoft.Sample' contains a definition conflicting with alias 'Guid'

The code creates an alias to the System.Guid type called Guid, and also creates its own type called Guid with a matching constructor interface. Later, the code creates an instance of the type Guid. To create this instance, the compiler must choose between the two different definitions of Guid. When the using-alias directive is placed outside of the namespace element, the compiler will choose the local definition of Guid defined within the local namespace, and completely ignore the using-alias directive defined outside of the namespace. This, unfortunately, is not obvious when reading the code.

When the using-alias directive is positioned within the namespace, however, the compiler has to choose between two different, conflicting Guid types both defined within the same namespace. Both of these types provide a matching constructor. The compiler is unable to make a decision, so it flags the compiler error.

Placing the using-alias directive outside of the namespace is a bad practice because it can lead to confusion in situations such as this, where it is not obvious which version of the type is actually being used. This can potentially lead to a bug which might be difficult to diagnose.

Placing using-alias directives within the namespace element eliminates this as a source of bugs.

  1. Multiple Namespaces

Placing multiple namespace elements within a single file is generally a bad idea, but if and when this is done, it is a good idea to place all using directives within each of the namespace elements, rather than globally at the top of the file. This will scope the namespaces tightly, and will also help to avoid the kind of behavior described above.

It is important to note that when code has been written with using directives placed outside of the namespace, care should be taken when moving these directives within the namespace, to ensure that this is not changing the semantics of the code. As explained above, placing using-alias directives within the namespace element allows the compiler to choose between conflicting types in ways that will not happen when the directives are placed outside of the namespace.

How to Fix Violations To fix a violation of this rule, move all using directives and using-alias directives within the namespace element.

JaredCacurak
@Jared - as I noted in my answer, my prefered workaround / solution is to only ever have one class per file. I think that this is a fairly common convention.
benPearce
Indeed, it's also a StyleCop rule! SA1402: A C# document may only contain a single class at the root level unless all of the classes are partial and are of the same type. Showcasing one rule by breaking another just drips with wrong sauce.
Task