#532 – Using Identically Named Types from Different Assemblies

If you want to use two types from different assemblies that have exactly the same name, including the namespace, your application won’t know which type to use.  The fully qualified type names are identical and you’ll get an error.

You can use both types in your project by providing an extern alias for the namespace hierarchy in one of the DLLs.

In Visual Studio, in your application, select the reference to one of the two assemblies.  Change the Aliases property from global to a new name.

Now include an extern alias statement in your code, using the same name.  Then use this alias to reference types in the aliased assembly.

using DogLibrary;   // FirstDogLibrary.dll

namespace ConsoleApplication1
{
    extern alias AnotherLib;

    class Program
    {
        static void Main()
        {
            // DogLibrary.Dog in FirstDogLibrary.dll
            Dog d = new Dog("Kirby", 12);

            // DogLibrary.Dog in AnotherDogLibrary.dll
            AnotherLib::DogLibrary.Dog d2 = new AnotherLib::DogLibrary.Dog("JRT", "Jack");
        }
    }
}

#531 – Best Practices for Naming Namespaces

In C#, a namespace declaration specifies the name of the namespace and you can use any valid C# identifier as the name.  However, it’s generally considered good practice to follow the suggestions listed below when naming namespaces.

  • Use Pascal Casing for each portion of the namespace, capitalizing the first letter of each word.  E.g. Acme.AfricanAnimalLibrary
  • Do not use underscores
  • Use sub-namespaces to organize/group related namespaces
  • The highest two levels of namespaces should follow the pattern CompanyName.ProductName or CompanyName.TechnologyName.  E.g. Acme.SearchEngine.Logging or Acme.Rendering.3DTools


Incorporating your company or organization name into the namespace hierarchy helps ensure that your types are globally unique.

#530 – Namespaces vs. Assemblies

In .NET, code is organized into both assemblies and namespaces.

  • An assembly is a physical file containing a number of types (.exe or .dll)
  • namespace is a logical grouping representing a parent name that various types belong to

An assembly can contain types belong to one or more namespaces.  Types belonging to a single namespace can be contained in a single assembly, or spread across multiple assemblies.

Code can reference types within another assembly after including a reference to that assembly in the current project.

Code can reference types in another namespace by using the full name of the type that includes the namespace, or with an using directive.

The example below shows two assemblies, both .DLL files, containing some types.  Each assembly contains types belonging to more than one namespace.  And each namespace shown is spread across both assemblies.

#529 – The using Directive Can Create an Alias for a Namespace

The most common use of the using directive is to bring types within a specified namespace into scope, so that they can be referenced directly in your code.

using DogLibrary;
using DogLibrary.Utility;

You can also use the using directive to create an alias for a namespace, which you can then use to access the types in that namespace.

In the example below, we have two different namespaces that each contain a DogLogger type.  Instead of having to list the fully qualified name of either DogLogger type when we use it, we can assign a shorter alias to refer to the containing namespace.

using U1 = DogLibrary.Utility.StandardLogging;
using U2 = DogLibrary.Utility.AlternateLogging;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            // Short for DogLibrary.Utility.StandardLogging.DogLogger
            U1.DogLogger log1 = new U1.DogLogger(@"C:\log1.txt");

            // Short for DogLibrary.Utility.AlternateLogging.DogLogger
            U2.DogLogger log2 = new U2.DogLogger(@"C:\log2.txt");
        }
    }
}

#527 – Defining a Nested Namespace Using Dot Notation

If you are defining a type that exists in a nested namespace, there are two ways to define the namespace.  You can nest the namespace keywords or you can use a dot notation to define the full namespace path.

Let’s say that we’re defining the new type DogLogger and placing it in the DogLibrary.Utility namespace.  You can nest the namespace keywords as shown below.

namespace DogLibrary
{
    namespace Utility
    {
        public class DogLogger
        {
        }
    }
}

You can also just include a single namespace keyword, fully specifying the DogLibrary.Utility namespace.

namespace DogLibrary.Utility
{
    public class DogLogger
    {
    }
}

#526 – Using Statements Can Alias Nested Namespaces

If you have a type defined in a nested namespace, e.g. type DogLogger defined in the DogLibrary.Utility namespace, you can include a using statements that aliases the inner namespace.

In the example below, we have two using statements.  One provides an alias for the outer DogLibrary namespace, so that you can use types from the DogLibrary namespace by just using the type name.  The second aliases the DogLibrary.Utility namespace, so that you can use types defined in the inner namespace.

using DogLibrary;
using DogLibrary.Utility;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            // DogLibrary.Dog
            Dog d = new Dog();

            // DogLibrary.Utility.DogLogger
            DogLogger logger = new DogLogger();
        }
    }

#525 – Namespaces Can Be Nested

You can define a namespace at the top-level of a source file or you can define a namespace within another namespace.  When you define a namespace within another namespace, you can refer to the inner namespace using a dotted (outer.inner) syntax.

In the example below, we have a Dog class defined within the top-level DogLibrary namespace.  The full name for this type is DogLibrary.Dog.  We also define a Utility namespace within the DogLibrary namespace, and a DogLogger class whose full name is then DogLibrary.Utility.DogLogger.

namespace DogLibrary
{
    public class Dog
    {
    }

    namespace Utility
    {
        public class DogLogger
        {
        }
    }
}

#524 – All Types Within a Namespace Must Be Unique

You can create more than one type with the same name, as long as the exist in different namespaces.  But within a particular namespace, the name of every type must be unique.

In the example below, we declare a Dog class in both the EarthDogs and AlienDogs namespaces.

namespace EarthDogs
{
    public class Dog
    {
        public string Name { get; set; }

        public void Bark()
        {
            Console.WriteLine("Woooof");
        }
    }
}

namespace AlienDogs
{
    public class Dog
    {
        public string Name { get; set; }

        public void Bark()
        {
            Console.WriteLine("Snarkzuggrootzen");
        }
    }
}

(In practice, for these classes, you’d probably instead declare a Dog parent class and subclasses EarthDog and AlienDog, which would override the Bark method).

#523 – The using Directive Allows Omitting Namespace

A typical C# program will use types that are defined in a variety of namespaces.  Specifying the fully qualified type name that includes the namespace can become tedious.

using directive tells the compiler what namespaces to look for types in, avoiding the need for fully qualified type names.

Assume that we have a Dog type, defined in the DogLibrary namespace.  The fully qualified type name is DogLibrary.Dog.  But in the code fragment below, we can just use Dog as the type name, because of the using directive.

using DogLibrary;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            Dog kirby = new Dog();
            kirby.Bark();
        }
    }
}

So you can use a type name without its namespace if:

  • The type is defined in the same namespace as the current code
  • using directive for the type’s namespace is present

#522 – The Fully Qualified Name for a Type Includes the Namespace

If we define a Dog type in the DogLibrary namespace, the fully qualified name for the new type is DogLibrary.Dog.  You can use this full name when working with the type.

            DogLibrary.Dog kirby = new DogLibrary.Dog();
            kirby.Bark();

If you’re writing code that exists in the same namespace as a type, you can omit the namespace and just use the short version of the type name.

namespace DogLibrary
{
    public class Dog
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public void Bark()
        {
            Console.WriteLine("WOOOOOF!");
        }
    }

    public static class DogFactory
    {
        public static Dog MakeDog(string name, int age)
        {
            // Can just use "Dog" as type name
            Dog d = new Dog();
            d.Name = name;
            d.Age = age;
            return d;
        }
    }
}

Follow

Get every new post delivered to your Inbox.

Join 43 other followers