The random utterances of David Arno

Aliases: overcoming name conflicts part 2: extern alias

What is it?

Aliases provide a means of overcoming conflicts between namespaces and, for example, classes that use the same names. Part one of this article showed how to use the global alias and the “using” keyword to define local aliases to overcome namespace/ class name conflicts. Here we examine how to use the “extern alias” command to define our own global aliases that can overcome problems with two classes having exactly the same namespace and class name.

I’d recommend you read part one before proceeding as it builds on ideas introduced there.

Which C# version supports it?

Version 2 and above.

Why use it?

In situations where you have two or more assemblies that define exactly the same class names in the same namespaces and you need to reference two or more of them from the same assembly. In an ideal world, everyone would write classes that sit neatly inside well formed, unique, namespaces. In reality, short-cuts are all too easy and tempting and problems of name conflicts can occur.

How to use it

Imagine we need a really useful application that prints a set of constants to the console. Because there are so many constants in the world, we have split the task of listing them between two contractors. On will produce constants beginning a-m, the other n-z. Now being typical contractors, both submit a compiled assembly without any source, submit their invoices and are never heard from again. Unsurprisingly both used exactly the same name for their class too: UsefulConstants.Constants. So we have the following two classes that we need for our super-duper application:

namespace UsefulConstants
{
  public class Constants
  {
    public const double Pi = 3.1415;
  }
}

and

namespace UsefulConstants
{
  public class Constants
  {
    public const double e = 2.71828;
  }
}

The first attempt at a program to use these assemblies is shown below:

using System;
using UsefulConstants;

namespace ConstantPrinter
{
  class Program
  {
  static void Main()
  {
    Console.WriteLine("Pi={0}", Constants.Pi);
    Console.WriteLine("e={0}", Constants.e);
    Console.ReadKey();
  }
}
}

This attempt generates the following error messages:

error CS0433: The type 'UsefulConstants.Constants' exists in both
              '...\UsefulConstants1\bin\Debug\UsefulConstants1.dll' and
              '...\UsefulConstants2\bin\Debug\UsefulConstants2.dll'
error CS0117: 'UsefulConstants.Constants' does not contain
              a definition for 'e'

To understand what is going on, and how we can fix the problem, we need to turn to look at the references in detail. The following two graphics show the properties of the the two referenced assemblies, UsefulConstants1and UsefulConstants2:

Screen grab from VS2005

Screen grab from VS2005

The important thing here is the “Aliases” field. Both are set to “global”. As explained in part 1, all namespaces sit beneath the global alias. This isn’t completely true though. It is more correct to say that all namespaces sit beneath the global alias by default. So in this case we have:

global -- UsefulConstants - Constants
       '- UsefulConstants - Constants
       '- ConstantPrinter - Program

So from the perspective of Program, we have two UsefulConstants.Constants classes. As you may have guessed by now, we can fix this by moving one of them out of global, into our own alias space:

global -- UsefulConstants - Constants
       '- ConstantPrinter - Program
X      -- UsefulConstants - Constants

So first of all, we modify UsefulConstants2′s preferences to an alias of X:

Screen grab from VS2005

Now if we recompile, we just get the one error:

error CS0117: 'UsefulConstants.Constants' does not contain
              a definition for 'e'

To fix this error, we use the “extern alias” instruction and modify our Program.cs thus:

extern alias X;

using System;
using UsefulConstants;

namespace ConstantPrinter
{
  class Program
  {
    static void Main()
    {
      Console.WriteLine("Pi={0}", Constants.Pi);
      Console.WriteLine("e={0}", X::UsefulConstants.Constants.e);
      Console.ReadKey();
    }
  }
}

The first line, tells the compiler that there is an external alias X that it needs to use when compiling this file. We then use X as an alias to unambiguously refer to the UsefulConstants.Constants class in the UsefulConstants2 assembly. Now when we compile, everything works just fine. You can download the zipped up copy of the VS2005 solution files used in this “how to”, so that you can experiment with it yourself.

3 comments

3 Comments so far

  1. Notre August 25th, 2010 19:48

    Hi,
    Do you know if this still works in VS 2010? I’m having no luck getting it to work.
    Thanks!

  2. David Arno August 31st, 2010 10:54

    Hi Notre,

    I don’t yet have VS2010 as I rarely do any C# work these days, so I don’t know either way. Sorry.

  3. Phillip September 14th, 2010 09:36

    It is working with VS2010! Thanks Arno!

    extern alias YourExternAlias;
    using YourAlias = YourExternAlias.YourNamespace;

    YourAlias::YourClass xyz = new YourAlias::YourClass();