I have been running StyleCop over some C# code, and it keeps reporting that my using directives should be inside the namespace.
Is there a technical reason for putting the using directives inside instead of outside the namespace?
I have been running StyleCop over some C# code, and it keeps reporting that my using directives should be inside the namespace.
Is there a technical reason for putting the using directives inside instead of outside the namespace?
There is actually a (subtle) difference between the two. Imagine you have the following code in File1.cs:
// File1.cs
using System;
namespace Outer.Inner
{
class Foo
{
static void Bar()
{
double d = Math.PI;
}
}
}
Now imagine that someone adds another file (File2.cs) to the project that looks like this:
// File2.cs
namespace Outer
{
class Math
{
}
}
The compiler searches Outer before looking at those using directives outside the namespace, so it finds Outer.Math instead of System.Math. Unfortunately (or perhaps fortunately?), Outer.Math has no PI member, so File1 is now broken.
This changes if you put the using inside your namespace declaration, as follows:
// File1b.cs
namespace Outer.Inner
{
using System;
class Foo
{
static void Bar()
{
double d = Math.PI;
}
}
}
Now the compiler searches System before searching Outer, finds System.Math, and all is well.
Some would argue that Math might be a bad name for a user-defined class, since there's already one in System; the point here is just that there is a difference, and it affects the maintainability of your code.
It's also interesting to note what happens if Foo is in namespace Outer, rather than Outer.Inner. In that case, adding Outer.Math in File2 breaks File1 regardless of where the using goes. This implies that the compiler searches the innermost enclosing namespace before it looks at any using directive.
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 much of 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;
}
According to Hanselman - Using Directive and Assembly Loading... and other such articles there is technically no difference.
My preference is to put them outside of namespaces.
One wrinkle I ran into (that isn't covered in other answers):
Suppose you have these namespaces:
When you use using Something.Other outside of a namespace Parent, it refers to the first one (Something.Other).
However if you use it inside of that namespace declaration, it refers to the second one (Parent.Something.Other)!
There is a simple solution: add the "global::" prefix: docs
namespace Parent
{
using global::Something.Other;
// etc
}
Another subtlety that I don't believe has been covered by the other answers is for when you have a class and namespace with the same name.
When you have the import inside the namespace then it will find the class. If the import is outside the namespace then the import will be ignored and the class and namespace have to be fully qualified.
//file1.cs
namespace Foo
{
class Foo
{
}
}
//file2.cs
namespace ConsoleApp3
{
using Foo;
class Program
{
static void Main(string[] args)
{
//This will allow you to use the class
Foo test = new Foo();
}
}
}
//file3.cs
using Foo; //Unused and redundant
namespace Bar
{
class Bar
{
Bar()
{
Foo.Foo test = new Foo.Foo();
Foo test = new Foo(); //will give you an error that a namespace is being used like a class.
}
}
}
The technical reasons are discussed in the answers and I think that it comes to the personal preferences in the end since the difference is not that big and there are tradeoffs for both of them. Visual Studio's default template for creating .cs files use using directives outside of namespaces e.g.
One can adjust stylecop to check using directives outside of namespaces through adding stylecop.json file in the root of the project file with the following:
{
"$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
"orderingRules": {
"usingDirectivesPlacement": "outsideNamespace"
}
}
}
You can create this config file in solution level and add it to your projects as 'Existing Link File' to share the config across all of your projects too.
As a rule, external using directives (System and Microsoft namespaces for example) should be placed outside the namespace directive. They are defaults that should be applied in all cases unless otherwise specified. This should include any of your own organization's internal libraries that are not part of the current project, or using directives that reference other primary namespaces in the same project. Any using directives that reference other modules in the current project and namespace should be placed inside the namespace directive. This serves two specific functions:
The latter reason is significant. It means that it's harder to introduce an ambiguous reference issue that can be introduced by a change no more significant than refactoring code. That is to say, you move a method from one file to another and suddenly a bug shows up that wasn't there before. Colloquially, a 'heisenbug' - historically fiendishly difficult to track down.