CSharp/C# Tutorial - C# Namespaces






A namespace is a domain for type names. We can use namespace to organize classes, delegates etc.

Types are typically organized into hierarchical namespaces.

A namespace forms an integral part of a type's name.

We can think the namespace as the folder while the classes are files. In the file system we use forders to organizing files.

The namespace keyword defines a namespace for types within that block.

For example:


namespace Outer.Middle.Inner { 
    class Class1 {} 
    class Class2 {} 
} 

The dots in the namespace indicate a hierarchy of nested namespaces.

The code that follows is semantically identical to the preceding example:


namespace Outer { 
    namespace Middle {
        namespace Inner { 
            class Class1 {} 
            class Class2 {} 
        } 
    } 
} 

We can refer to a type with its fully qualified name.

For example, we could refer to Class1 in the preceding example as Outer.Middle.Inner.Class1.

Types not defined in any namespace are in the global namespace.





The using Directive

The using directive imports a namespace, allowing you to refer to types without their fully qualified names.

The following imports the previous example's Outer.Middle.Inner namespace:


using Outer.Middle.Inner; 

class Test { 
    static void Main() { 
        Class1 c; // Don't need fully qualified name
    } 
} 




Name scoping

Names declared in outer namespaces can be used unqualified within inner namespaces.

In this example, the names Middle and Class1 are implicitly imported into Inner:


namespace Outer { 
    namespace Middle {
        class Class1 {}
        namespace Inner { 
            class Class2 : Class1 {} 
        } 
    } 
} 

To refer to a type in a different branch of your namespace hierarchy, use a partially qualified name.

In the following example, we base MyClass on Common.MyBase:


namespace Outer { 
    namespace Common {
        class MyBase {} 
    } 
    namespace MyNamespace {
        class MyClass : Common.MyBase {} 
    } 
} 

Name hiding

If the same type name appears in both an inner and an outer namespace, the inner name wins.

To refer to the type in the outer namespace, you must qualify its name.

For example:


namespace Outer { 
    class myMethod { } 
    namespace Inner { 
        class myMethod { } 
        class Test { 
            myMethod f1; // = Outer.Inner.myMethod 
            Outer.myMethod f2; // = Outer.myMethod 
        } /*from w ww .j a  v  a 2 s . c o m*/
    } 
} 

Repeated namespaces

You can repeat a namespace declaration, as long as the type names within the namespaces don't conflict:


namespace Outer.Middle.Inner {
     class Class1 {} 
} 
namespace Outer.Middle.Inner { 
    class Class2 {} 
} 

Nested using directive

We can nest a using directive within a namespace.

In the following example, Class1 is visible in one scope, but not in another:


namespace Outer { 
    class Class1 {} 
} //from w  ww.ja  v a2s.  com
namespace N2 { 
    using Outer;
    class Class2 : Class1 {} 
} 
namespace N2 { 
    class Class3 : Class1 {} // Compile-time error 
} 

Aliasing Types and Namespaces

Importing a namespace can result in type-name collision.

We can import just the specific types you need, giving each type an alias.

For example:


using PropertyInfo2 = System.Reflection.PropertyInfo; 
class Program { PropertyInfo2 p; } 

An entire namespace can be aliased, as follows:


using R = System.Reflection; 

class Program { 
   R.PropertyInfo p; 
}