Namespaces

Summary

namespace

The namespace keyword is used to declare a scope. This namespace allows you group logically-related entities together

Compilation Units

A compilation-unit defines the overall structure of a source file. A C# program consists of one or more compilation units, each contained in a separate source file. When a C# program is compiled, all compilation units are processed together. Thus compilation units can depend on each other, and could possible produce cyclic dependency.

Each compilation unit has an unnamed namespace called the global namespace. Any identifier (class, struct, interface, delegate, and enum) declared outside a namespace will become part of the global namespaces. For example:

// File a.cs
class A { ... }

// File b.cs
class B { ... }

These two files will produce two compilation units that contribute to the global namespace. And because the two compilation units join the same namespace, it would be a compile-time error if one of them declared a class with the same name that was present in another compilation unit. For example, A.cs cannot declare a class called B because class B already exists in the global namespace 

Namespace Declaration

A namespace takes the form of:

namespace name1.name2...
{
    type-declarations;
}

where type-declaration can be one of the following:

When a namespace occurs as a top-level declaration in a compilation-unit, the namespace becomes a member of the global namespace. When a namespace declaration occurs within the declaration of another namespace, the inner namespace becomes a member of the outer namespace. Recall that namespaces are implicitly public and cannot include any access modifiers.

When a type-declaration for a Type T (class, interface, strcut, delegate, or enum) appears as a top-level declaration in a compilation unit, the declaration becomes a member of the global namespace. The fully qualified name of the newly declared type is simply T.

Also note that the following namespace declarations are equivalent, with the latter being preferred because it allows to define nested namespaces without lexically nesting namespace declarations:

namespace A.B
{
    class X { ... }
    class Y { ... }
}

namespace A
{
    namespace B
    {
        class X { ... }
        class Y { ... }
    }
}

Finally, namespace declarations are open-ended; two namespace declarations with the same fully qualified name contribute to the same declaration namespace. For example, Files a.cs and b.cs both contribute to namespace X:

// File a.cs
namespace X
{
    class A { ... }
}

// File b.cs
namespace X
{
    class B { ... }
}

The :: Operator (C # 2.0)

The :: operator is the namespace-alias qualifier  and is used to provide more control over accessing namespaces members. It is used when complex namespaces result in certain names being hidden by others. The global:: alias allows access to the root System namespace if it happened to be hidden by an entity in your code. The following example illustrates:

 class System
{
    private int Console = 10;
    public void Test()
    {
        // You cannot access class System.Console anymore
        Console = 10;

        // Cannot even access Console using System.Console since System is the
        // name of this class. Solution is to use a namespace-alias qualifier

        global::System.Console.WriteLine("hello");
    }
}

Microsoft.VisualBasic namespace

The Microsoft.VisualBasic.MyServices namespace provides easy and simple access to a number of .NET Framework classes, allowing you to write code that interacts with the computer, application, settings, resources,  an so on. Although this feature was originally designed for use with Visual Basic,  the MyServcies namespace can also be used in C# applications.

// Some features of Microsoft.VisualBasic.Devices
Microsoft.VisualBasic.Devices.Network net = new Network();
bool bSuccessfulPing = net.Ping("localhost", 1000);

// Play some sounds
Microsoft.VisualBasic.Devices.Audio audio = new Audio();
audio.PlaySystemSound(global::System.Media.SystemSounds.Hand);

Microsoft.VisualBasic.ApplicationServices.User user = new Microsoft.VisualBasic.ApplicationServices.User();
string name = user.Name;

using

Recall that the using keyword has two major uses:

using Directives

using directives facilitate the use of namespaces and types defined in other namespaces by:

  1. Creating an alias for a namespace. This introduces an identifier that serves as an alias for a namespace or a type within the immediately enclosing compilation unit or namespace
  2. Permitting the use of type in a certain namespace without having to fully qualify the type name.

For example,

using ODBC = Microsoft.Data.ODBC;    // using directive use 1
using System.Diagnostics;            // using directive use 2

using MyClassAlias = A.MyClass;      // An alias to a class
namespace A
{
    public class MyClass { ... }
}

namespace N1.N2
{
    public class A { ... }
}
namespace N3
{
    public class B : N1.N2.A { ... }   // or

    using A = N1.N2.A;
    public class B : A { ... }
}

using Statement

The using statement defines a scope at the end of which an object will be disposed. The using statement takes the following form:

using ( expression | type identifier = initializer )
{
    ...
}

The using statement is exited either at the end of the using statement or if an exception is thrown and control leaves the statement block. Note that the object you instantiate must implement IDisposable. For example:

public class TimeTracer : IDisposable
{
    // Data members
    string strName;

    // Constructor
    public Tracer(string name )
    {
        strName = name;
        Trace.WriteLine( "Entering " + strName + " at " + DateTime.Now );
    }

    // IDisposable implementation
    public void Dispose()
    {
        Trace.WriteLine( "Exiting " + strName + " at " + DateTime.Now );
    }
}

// Using using
using (Tracer ob = new Tracer( "foo" ) )
{
    ...
}    // IDispose called here