I often notice the code where the libraries are connected not in front of the namespace , but inside. I wonder why they do this and what are the fundamental differences?

The usual connection method:

 using System; using System.Linq; using System.Collections.Generic; namespace Domain { } 

Connection method inside namespace :

 namespace Domain { using System; using System.Linq; using System.Collections.Generic; } 
  • one
    @VladD, and translate? ;-) - Grundy
  • one
    @VladD, The principle is clear, but I think someone in Russian would like to read. - Lightness
  • @Lightness: I would translate, but dump on vacation after about 5 minutes :) Let someone else write a good answer on the topic. - VladD
  • @VladD, I started :-) but maybe someone will have time earlier :-) - Grundy

2 answers 2

Translation of the answer to a similar question in English

There really is a difference.
Imagine that there is a File1.cs file with the following code:

 // File1.cs using System; namespace Outer.Inner { class Foo { static void Bar() { double d = Math.PI; } } } 

Now imagine that someone added another file ( File2.cs ):

 // File2.cs namespace Outer { class Math { } } 

The compiler will find Outer before it Outer.Math at using outside the namespace, so it will find Outer.Math instead of System.Math . Unfortunately (or perhaps fortunately?), Outer.Math no PI member in Outer.Math , so the compiler will start swearing at Math.PI in the File1.cs file.

Everything will change if you put using inside a namespace definition, like this:

 // File1b.cs namespace Outer.Inner { using System; class Foo { static void Bar() { double d = Math.PI; } } } 

Now the compiler will find System before Outer , and will use System.Math , and everything will be fine.

Some argue that Math is a bad name for a custom class because such a class already exists in System ; The fact is that only here there is a difference and this will affect the code maintainability.

It is also interesting what can happen if Foo is declared in the Outer namespace, not Outer.Inner . In this case, adding Outer.Math to File2 breaks File1 no matter where using is located. This means that the compiler searches in the innermost namespace before looking at any using expressions.

    A translation of one of the answers should 'using' statements be inside or outside the namespace?

    To begin with, pay attention to the fact that the namespace is defined as follows:

     namespace MyCorp.TheProduct.SomeModule.Utilities { ... } 

    equivalent to defining multiple nested namespaces:

     namespace MyCorp { namespace TheProduct { namespace SomeModule { namespace Utilities { ... } } } } 

    If you connect an assembly outside the space, then it will be visible inside all spanning spaces. The search for a specific type can be expressed like this: firstly, the search for a match in the innermost "scope", if nothing was found there to go up one level and search there, and so on, until a match is found. If there is more than one match at any level, you will get a compiler warning. If not found, issue an error at compile time.

    Now, let's be more clear about what this means on a concrete example with two main conventions.

    (1) With usings outside:

     using System; using System.Collections.Generic; using System.Linq; //using MyCorp.TheProduct; <-- uncommenting this would change nothing using MyCorp.TheProduct.OtherModule; using MyCorp.TheProduct.OtherModule.Integration; using ThirdParty; namespace MyCorp.TheProduct.SomeModule.Utilities { class C { Ambiguous a; } } 

    In the above case, to find out the type of Ambiguous , the search goes in the following order:

    1. Nested types inside C (including inherited nested types)
    2. Types in the current namespace MyCorp.TheProduct.SomeModule.Utilities
    3. Types in the MyCorp.TheProduct.SomeModule
    4. Types in MyCorp.TheProduct
    5. Types in MyCorp
    6. Types in the global namespace
    7. Types in System , System.Collections.Generic , System.Linq , MyCorp.TheProduct.OtherModule , MyCorp.TheProduct.OtherModule.Integration and ThirdParty

    Other convention:

    (2) With usings inside:

     namespace MyCorp.TheProduct.SomeModule.Utilities { using System; using System.Collections.Generic; using System.Linq; using MyCorp.TheProduct; // MyCorp can be left out; this using is NOT redundant using MyCorp.TheProduct.OtherModule; // MyCorp.TheProduct can be left out using MyCorp.TheProduct.OtherModule.Integration; // MyCorp.TheProduct can be left out using ThirdParty; class C { Ambiguous a; } } 

    Now search by type Ambiguous goes in the following order:

    1. Nested types inside C (including inherited nested types)
    2. Types in the current namespace MyCorp.TheProduct.SomeModule.Utilities
    3. Types in System , System.Collections.Generic , System.Linq , MyCorp.TheProduct , MyCorp.TheProduct.OtherModule , MyCorp.TheProduct.OtherModule.Integration and ThirdParty
    4. Types in the MyCorp.TheProduct.SomeModule
    5. Types in MyCorp
    6. Types in the global namespace

    (Note that MyCorp.TheProduct was part of "3." and, therefore, is not required between "4." and "5."

    Concluding remarks

    Regardless of whether you are using inside or outside a namespace declaration, there is always a chance that someone later adds a new type with the same name to one of the spaces, which has a higher priority.

    In addition, if the nested namespace has the same name as the type, this can cause problems.

    It is always dangerous to move using from one place to another, as the search hierarchy changes, and another type can be found. So choose one convention and stick to it so that you never have to move using .

    The default Visual Studio template, by default, is using outside of the namespace (for example, if you create a new class in a new file).

    One (tiny) advantage of using outside the namespace, you can use directives for a global attribute, for example [assembly: ComVisible(false)] instead of [assembly: System.Runtime.InteropServices.ComVisible(false)] .

    • one
      and correct the errors of automatic translation? but somehow it is not in Russian in some places, the letters and words are correct, and the text is clumsy. - rdorn pm