#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");
        }
    }
}

#528 – Types Are Organized by Namespace in the Object Browser

You can use the Object Browser in Visual Studio to get information about types and their members.  Typically, you’d use this to get information for types in an assembly that you did not author.

In the example below, we right-click on the DogLibrary assembly, which the ConsoleApplication1 application references and select View in Object Browser.

Once the Object Browser window opens, we can see that the DogLibrary assembly contains types in two namespaces–DogLibrary and DogLibrary.Utility.

We can expand either of the namespaces to see the types that it includes and then click on a type to see its members.

#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).

No Post Today

2,000 Things / C# is on hiatus today–back tomorrow.

#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;
        }
    }
}

#521 – Namespaces Help Organize Types

In C#, a namespace is a collection of related types.  The fully qualified name of every type actually includes the namespace that it’s defined in.

You use the namespace keyword to define a namespace.  All types defined within the pair of braces that follow the namespace name then belong to that namespace.

In the example below, the Dog class belongs to the DogLibrary namespace.

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

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

Because Dog is defined within the DogLibrary namespace, the fully qualifed name of the Dog type is DogLibrary.Dog.