Click here to Skip to main content
Click here to Skip to main content

Understanding Namespaces in C# 2.0

, 20 Dec 2006 CPOL
Rate this:
Please Sign up or sign in to vote.
This articles specifies the problems with namespaces in earlier versions of C# and how C# 2.0 handles them

Introduction

Namespace in .NET is an additional information. If provided, it will enable unique naming of types within an assembly. This articles assumes C# knowledge and all the issues/resolutions provided are applicable to C# 1.1/2.0

For example, you can have a class called Console in your assembly, within a namespace named, say, MyNamespace. System namespace also has a class named Console. We can use both classes in the program .

Problems with Namespaces in 1.1

If you worked on a large project in .NET in the past, you must have faced some problems with namespaces. Namespaces were introduced in .NET to eliminate the naming collisions between different code developed at different locations. But as larger projects were developed, some shortcomings were observed. Some of them included:

  1. Same typename can be used in multiple namespaces. In this scenario, types in local namespaces can mask types in global namespaces. This leads to an ambiguous situation.
  2. Same typenames can be used in multiple assemblies. When these assemblies were used in the same application, again, there will be ambiguity in referencing the types.
  3. Using aliases can lead to ambiguous identification. Aliases can mask the type if care is not taken.

Namespaces in 2.0

To address all the issues that arose in the previous version, 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. Namespace aliasing also offers greater flexibility.

Let's look at the following piece of code:

namespace Aeroplane
{
    interface IGoodsCarrier
    {
    }

    interface IPassengerCarrier
    {
    }

    namespace Boeing
    {
        class Boeing737 : IPassengerCarrier { ... }
    }

    namespace AirBus
    {
        class AirBusA340 : IPassengerCarrier { ... }
    }
}

using Manufacturer = Aeroplace.AirBus;

namespace Aeroplane
{
    namespace Company { ... }

    class Program
    {
        static void Main()
        {
            IPassengerCarrier carrier = new Manufacturer.AirBusA340();
        }
    }
}

This works well with both 1.1 and 2.0, but if somebody adds:

namespace AeroPlane
{
    namespace Manufacturer { ... }
}

1.1 will throw a compile time exception as there is a colliding namespace with the alias qualifier.

2.0 addresses this issue with a minor syntax change. We'll now use :: operator to resolve the ambiguity.

//replace
//IPassengerCarrier carrier = new Manufacturer.AirBusA340();
//with
IPassengerCarrier carrier = new Manufacturer::AirBusA340();

This will unambiguously refer to Aeroplane.AirBus.

:: operator identifies the left hand side operator of the instruction as an alias and not as 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. Let's 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, most of the times in Utility classes.

Let's 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 the 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();
        }
    }
}

Summary

Though these things seem to be very uncommon situations, in large projects, these are quite common and sometimes very frustrating. Now, we have these changes in C# 2.0 which will help working with large projects without frustration.

History

  • 20th December, 2006: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Sidhartha Gundavarapu
Microsoft
India India
I'm working as a Consultant at Microsoft Global Services and like to spend my spare time investigating new stuff and write articles about the ones that are less discussed about. Please feel free to send your comments/suggestions/corrections on any of my work.

Comments and Discussions

 
GeneralMy vote of 1 PinmemberMember 894893729-Jun-12 22:11 
Questionsource code Pinmemberwalkie8610-May-12 6:10 
GeneralAaah, the solution to my compiler warnings PinmemberAlistair Lacy5-Sep-07 7:54 
GeneralRe: Aaah, the solution to my compiler warnings PinmemberSidhartha Gundavarapu5-Sep-07 15:59 
GeneralRe: Aaah, the solution to my compiler warnings PinmemberAlistair Lacy7-Sep-07 5:53 
GeneralSo much for KISS PinmemberSteven A Bristol21-Dec-06 2:34 
GeneralRe: So much for KISS PinmemberSidhartha Gundavarapu21-Dec-06 5:08 
GeneralNamespace/packages in C#/Java PinmemberJan Seda20-Dec-06 23:24 
GeneralRe: Namespace/packages in C#/Java Pinmemberdadeval21-Dec-06 0:21 
GeneralRe: Namespace/packages in C#/Java PinmemberJan Seda21-Dec-06 2:17 
GeneralRe: Namespace/packages in C#/Java PinmemberSidhartha Gundavarapu21-Dec-06 5:12 
GeneralRe: Namespace/packages in C#/Java PinmemberJan Seda21-Dec-06 13:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.1411028.1 | Last Updated 20 Dec 2006
Article Copyright 2006 by Sidhartha Gundavarapu
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid