Namespaces in C#2.0

To address all the issues that arise in the previous version of .Net,, C# 2.0 introduced some new features like:
 
1. Namespace aliasing
2. global :: operator
3. Extern Aliasing
 
Namespace Aliasing
 
With Namespace aliasing parallel namespaces are much more convenient and namespace aliasing also offers greater flexibility.
 
Let’s look at the following piece of code:
 
namespace Bus 
{
    interface IGoodsCarrier
    {
    }

    interface IPassengerCarrier
    {
    }

    namespace ACBus
    {
        class Mahindra : IPassengerCarrier { ... }
    }

    namespace NonACBus
    {
        class Ashoka : IPassengerCarrier { ... }
    }
}

using Manufacturer = Bus.NonACBus;

namespace Bus
{
    namespane Company { ... }

    class Program
    {
        static void Main()
        {
            IPassengerCarrier carrier = new Manufacturer.NonACBus();
        }
    }
}
 
This works well with both 1.1 and 2.0, but if somebody adds
 
namespace Bus
{
    namespace Manufacturer { ... }
}
 
.Net version 1.1 will throw a compile time exception as there is a colliding namespace with the alias qualifier.

.Net version 2.0 addresses this issue with a minor syntax change. We’ll now use :: operator to resolve this ambiguity.

 
//replace
//IPassengerCarrier carrier = new Manufacturer.NonACBus ();
//with
IPassengerCarrier carrier = new Manufacturer::NonACBus();
 
This will unambiguously refer to ACBus, NonACBus.

:: Operator identifies the left hand side operator of the instruction as an alias and not a namespace.

 
global:: Operator
 
To understand the importance of this operator, let’s look at this sample code
 
namespace MyOrg
{
    namespace System
    {
        public class Console { ... }

        public class Program
        {
            static void Main()
            {
                 // problem. ambiguous call to 
Console as it is //available in System namespace and MyOrg.System //namespace
                Console.WriteLine("Hello");     

                // this is also ambiguous
                System.Console.WriteLine("Hello");     
                // these code lines will not refer to the top level //System.Console
            }
        }
    }
}
 
global:: operator will unambiguously refer to the top level scope in these situations lets check the modified code
 
namespace MyOrg
{
    namespace System
    {
        public class Console { ... }

        public class Program
        {
            static void Main()
            {
                 // unambiguous call. 
Calls Console class available at //MyOrg.System namespace
                Console.WriteLine("Hello"); 

                // this is also unambiguous
                global::System.Console.WriteLine("Hello"); 
            }
        }
    }
}
 
External Aliasing
 
If you are working in a large organization, you might have observed that developers working on two different assemblies define the same typename in the same namespace. E.g. Most of the times in Utility classes
 
lets look at this code to understand this situation
 
//in assembly - first.dll
namespace MyOrg.Utility
{
    public class Helper
    {
        public static bool SendMail() 
        { 
            //sends mail through the SmtpServer 
        }
    }
}

//in assembly - second.dll
namespace MyOrg.Utility
{
    public class Helper
    {
        public static bool SendMail() 
        { 
            //sends mail from the mail account of the user 
        }
    }
}

//consumer code - references to both first.dll and second.dll
namespace MyOrg.Utility
{
    public class Program
    {
        public static void NotifyUser()
        {
            //this will fail at compile time 
as the assembly namespaces //are colliding
            Helper.SendMail();
        }
    }
}
 
External aliasing can resolve ambiguous references to the namespaces. External aliasing provides assembly qualified namespace aliases. extern is the keyword that should be used to provide the assembly qualified namespaces.
 
Defining the extern alias involves two things. Firstly, we need to define the extern alias in the source code of the consumer and we also need to map the aliases to the assemblies through the compiler options.
 
Let us look at how the above program changes
 
//consumer code - references to both first.dll and second.dll

//while compiling the following references should be user
//C:\Code>csc /r:First=first.dll /r:Second=second.dll Program.cs

//this can be done from VS 2005, by 
opening the properties of the //referenced dll's properties 
//and providing aliases in the Aliases property

extern alias First;        //should match the alias provided in the       //compiler options
extern alias Second;       //should match the alias provided in teh //compiler options

using FirstUtility = First::MyOrg.Utility;
using SecondUtility = Second::MyOrg.Utility;

namespace MyOrg.Utility
{
    public class Program
    {
        public static void NotifyUser()
        {
            //this will not fail 
            FirstUtility.Helper.SendMail();
            SecondUtility.Helper.SendMail();
        }
    }
}
 
 
. .