#987 – The using Directive Can Create an Alias for a Type

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

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

We might do the above if we had an identically named type in each of the two namespaces so that we could then prefix the type with the appropriate namespace.

U1.DogLogger log1 = new U1.DogLogger(@"C:\log1.txt");
U2.DogLogger log2 = new U2.DogLogger(@"C:\log2.txt");

We can also use the using directive to create an alias for a specific type.  For the example above, we could do the following:

using Logger1 = DogLibrary.Utility.StandardLogging.DogLogger;
using Logger2 = DogLibrary.Utility.AlternateLogging.DogLogger;

We could then use the alias directly as a type name:

            // Short for DogLibrary.Utility.StandardLogging.DogLogger
            Logger1 log1 = new Logger1(@"C:\log1.txt");

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

#673 – Types Used in using Statement Must Implement IDisposable

The using statement is a shortcut for a try/finally block where the Dispose method is automatically called on any objects instantiated as part of the using statement.

            using (StreamWriter sw = new StreamWriter(@"D:\Hi.txt"))
            {
                sw.Write("Hi !");
            }
            // StreamWriter.Dispose automatically called

Because the Dispose method is called automatically on all objects instantiated as part of the using statement, each object must belong to a type that implements IDisposable.  The example below leads to a compile-time error because Dog does not implement IDisposable and therefore does not have a Dispose method.

            using (Dog d = new Dog("Kirby", 15))
            {
                d.Bark();
            }

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

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

#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

#432 – Initialize Multiple Objects in a using Statement

The using statement defines the scope in which an object can be used, automatically calling the object’s Dispose method when it goes out of scope.

You can declare and initialize more than one object in a using statement, as long as they are all the same type.  All of the objects will be disposed when the scope of the using statement ends.

            using (StreamWriter writer = new StreamWriter(@"D:\Remember.txt"),
                   writer2 = new StreamWriter(@"D:\Legacy.txt"),
                   writer3 = new StreamWriter(@"D:\Clothing.txt"))
            {
                writer.Write("RIP Steve Jobs, 1955-2011");
                writer2.Write("Apple II, Macintosh, iMac, iPhone, iPad");
                writer3.Write("Jeans. Turtleneck.");
            }

#431 – The using Statement Automates Invocation of the Dispose Method

A class may implement the IDisposable interface, providing a Dispose method, to allow for deterministic destruction.  Client code calls Dispose when it is done using the object, telling it to release resources that it might be holding.

It can be hard to ensure that you always call Dispose when appropriate, especially when exceptions occur.

The using statement in C# specifies the scope in which you want to use an object and guarantees that the Dispose method will be called when the object goes out of scope.

            using (StreamWriter writer =
                new StreamWriter(@"D:\Remember.txt"))
            {
                writer.Write("RIP Steve Jobs, 1955-2011");
            }

If we look at the IL generated for the using statement, we can see that it is converted to a try/finally block and the Dispose method of the StreamWriter object is called in the finally block.