Monday, July 3, 2017

Using statement inside Vs outside

A namespace declaration looks like: MyCorp.TheProduct.SomeModule.Utilities
This could be equivalence


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

The rule to resolve the namespace is: First, search the inner most "scope" for a match. If nothing is found then goes out 1 level, continue searching,next and so on... Until a match is found.
Let check the code

With using outside

using System;
using System.Collections.Generic;
using System.Linq;
//using MyCorp.TheProduct; <-- br="" change="" nothing="" this="" uncommenting="" would=""> 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 what type Ambiguous is, the search goes in this order:


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



With usings inside:
namespace MyCorp.TheProduct.SomeModule.Utilities
{
   using System;
   using System.Collections.Generic;
   using System.Linq;
   using MyCorp.TheProduct;
   using MyCorp.TheProduct.OtherModule;
   using MyCorp.TheProduct.OtherModule.Integration;
   using ThirdParty;

   class C
   {
      Ambiguous a;
   }
}


Now, search for the type Ambiguous goes in this 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 namespace MyCorp.TheProduct.SomeModule
  5. Types in MyCorp (MyCorp.TheProduct is already searched)
  6. Types in the null namespace (the global namespace)



No matter what we put the using inside or outside the namespace declaration, there's always the possibility that someone add a new type later with identical name ambiguous to one of the namespaces which has higher priority.
Also, if a nested namespace has the same name as a type, it can cause problems.

It's always dangerous to move the using form outside to inside and vice versa. The search hierarchy is changed and another type would be found. Therefore, chose one convention and stick to it.

One advantage of having using outside is that we can rename the using directives look like using AC=System.Security.AccessControl

No comments:

Post a Comment