views:

496

answers:

7

Given this declaration:

using System;
using System.Collections;
using System.Collections.Generic;

namespace AProject.Helpers
{
    public static class AClass
    {

and this declaration

namespace AProject.Helpers
{
    using System;
    using System.Collections;
    using System.Collections.Generic;

    public static class AClass
    {

are there any difference in any sense between them? Or is just a difference in coding styles?

I allways used to declared my classes like the first, but recently noticed that Microsoft uses the second.

+6  A: 

It makes the using directives local to that namespace, which in practice should make no difference since you're (hopefully) not declaring multiple types in multiple namespaces in a single source file.

Details here.

anelson
It can make a difference in an edge case. See the link in my answer.
Jon Skeet
A: 

I guess there might be reason to use the second alternative from a purist perspective, since it makes more obviously clear what the scope of the using directives is.

jerryjvl
A: 

In the first example, the using declarations are "global" to the whole file. In the second example, the using statements will only apply to the code wrapped up in the namespace block.

I think the only time this really matters is if you have more than one namespace in the file, and want to limit which namespace has access to each using declaration.

Andy White
+25  A: 

In the latter version the using directives only apply within the namespace declaration.

In most cases you'll only have a single namespace declaration:

// Using directives
...
namespace X
{
    // Maybe more using directives
    // Code
}
// End of file

The main difference is if you have multiple namespaces in the same file:

// Using directives
...
namespace X
{
    // Maybe more using directives
    // Code
}

namespace Y
{
    // Maybe more using directives
    // Code
}
// End of file

In this case the using directives in the namespace X declaration don't affect the code inside the namespace Y declaration, and vice versa.

However, that's not the only difference - there's a subtle case which Eric Lippert points out where it can affect the code even with just a single namespace declaration. (Basically if you write using Foo; inside the namespace X declaration, and there's a namespace X.Foo as well as Foo, the behaviour changes. This can be remedied using a namespace alias, e.g. using global::Foo; if you really want.)

Personally I'd stick to:

  • One namespace declaration per file (and usually one top-level type per file)
  • Using directives outside the namespace declaration
Jon Skeet
Great answer as usual Jon. +1
DoctaJonez
+2  A: 

The second can be ambiguous;

The top one makes it clear your after these namespaces:

  • System
  • System.Collections
  • System.Collections.Generic

While the second one will first look for these namespaces:

  • AProject.Helpers.System
  • AProject.Helpers.System.Collections
  • AProject.Helpers.System.Collections.Generic

And refer to them instead if they're found... If not, they'll both refer to the same namespaces.

The safer rewrite of the second one would be:

namespace AProject.Helpers
{
    using global::System;
    using global::System.Collections;
    using global::System.Collections.Generic;
}
Arjan Einbu
A: 

And for the process that Arjan points out, it's considered to be bad practice to declare usings inside your namespace. They can be implicitly overridden by another namespace.

Jonathan van de Veen
+1  A: 

Another important difference between them arises when using LINQ-to-SQL and the generated datacontext classes. For example, the Northwind sample database; initially, you get:

  • Northwind.dbml
    • Northwind.dbml.layout
    • Northwind.designer.cs

If you now want to extend the partial classes by adding your own Northwind.cs, you get

  • Northwind.dbml
    • Northwind.dbml.layout
    • Northwind.designer.cs
    • Northwind.cs

Amusingly, there is a bug in the code-generator (MSLinqToSQLGenerator) - which means that if the using directives are outside the namespace (like they are by default), it breaks - with the message:

The custom tool 'MSLinqToSQLGenerator' failed. Unspecified error

And the Northwind.designer.cs file gets deleted. No more data-context!

However, if you move the using directives inside the namespace (and re-run the custom tool - right click in solution explorer), it works correctly.

So: this isn't a language detail - it is simply a bug in the code generator; but there is a pretty big difference between "works correctly" and the generated code getting deleted...

Note you can also fix this simply by calling your file something different - such as NorthwindExtras.cs.

Freaky.

Marc Gravell