The Many Uses of "using"

As you probably already know, using directives can save you a lot of typing. Consider the following:

System.Collections.Specialized. NameValueCollection col = new System.Collections.Specialized.NameValueCollection();

By inserting this using directive,

using System.Collections.Specialized;

you can cut it down to this:

NameValueCollection col = new NameValueCollection();

Using “using” to Alias Namespaces

But that’s not all there is to using “using” (pun intended). With using, you can alias both namespaces and types, which is great for distinguishing between two classes with the same name in different namespaces. Say, for example, you have your own Console class, defined within your own namespace:

namespaceMyNamespace
{
 
class Console
 
{
   
public static void WriteLine(string message)
    {
     
System.Console.WriteLine(message);
    }
 
}
}

Within your main program you have two using statements, one for System and the other for MyNamespace.

usingSystem;
using MyNamespace;

When you try to call the WriteLine method of the Console class, the intellisense will warn you of the conflict:

Console Conflict

To resolve the conflict, you either have to use the fully qualified type name, MyNamespace.Console, or you can use an alias with the using directive, which is particularly helpful if it refers to several nested namespaces.

using my = MyNamespace;

Then incorporate it into your program as follows:

my. Console.WriteLine("hello");

Using “using” to Alias Types

Not only can using alias namespace, but it can also alias types. One of the things I really like about C# are the built-in type aliases. Instead of typing System.Int32, or even just Int32, you just type int. These’s something nice about that. Well, the neat thing (to use a nerd word) is that you can do the same thing, either with your own types, or with the built-in .Net Framework types.

For example, say you want to define your own alias so that it points to either Int32 or Int64 depending on a conditional compilation constant. Then, to change from one to the other, all you have to do is reset the constant.

#defineUSE_64
#if
USE_64
 
using myint = System.Int64;
#else
 
using myint = System.Int32;
#endif

static void Main()
{
 
Type
= typeof(myint);
Console
.WriteLine(t.ToString());
}

If USE_64 is defined, System.Int64 is written to the console; otherwise, the output is System.Int32.

global :: The Mother of All Namespaces

While we’re on the topic of aliases and namespaces, it’s a good time to bring up the “global” namespace, which resides on top of all the other namespaces in .Net. See what happens when you type global::

Global Namespace

First, you’ll notice that all other namespaces, including System, are defined under the “global” namespace. Secondly, the Program class is not defined within a namespace and therefore is included directly under global. This comes in handy especially when there’s a conflict between one of your classes and something that’s predefined in the .Net class libraries.

Let’s say you’ve defined a Console class in your own namespace, but you want to differentiate between it and System.Console. You can do that by prefixing the namespace with global, like so:

namespaceMyNamespace
{
 
public class Console
 
{
   
public static void WriteLine() { }
}

  class Program
  
{
    
static void Main()
    {
     
// This calls our local class
     
Console.WriteLine();
      // Use global to specify the Framework class
     
global::System.Console.WriteLine();
    }
  
}
}

Aliasing References

To top it all off, there’s also a way to alias namespaces and types in a specific assembly you’ve referenced. This is especially useful when you’re referencing two versions of an assembly, each with the same namespace structure. To make use of this facility, you need to compile your main assembly at the command-line using csc.exe. The alias for each assembly is specified with the /r switch, like so:

/r:Assem1=assembly1.dll
/r:Assem2=assembly2.dll

Then you can add the following directives at the very top of your class file:

extern alias Assem1
extern alias Assem2

This adds a root namespace, along side global, for each assembly. You prefix types in each assembly using the same syntax as global:

Assem1::MyNamespace.MyClass c1;
Assem2::MyNamespace.MyClass c1;

As you can see, there’s quite an arsenal at your disposal to help you avoid naming conflicts — with .Net 2.0, disambiguation has never been more enjoyable J

About Tony Sneed

Married with three children.
This entry was posted in Technical. Bookmark the permalink.

2 Responses to The Many Uses of "using"

  1. Josh Hidley says:

    “disambiguation” Haha.

    Cool new features (though aliasing namespaces with using was in 1.x). Thanks for the insightful explanations.

    But what’s up with the 2 colon syntax after global? Why not stick with dot? Incase you have a namespace named “global”? Why not just make it a keyword?

  2. Tony says:

    Uhh, yea. Not the most exciting topic :). Aliasing types was there in 1.x, but I didn’t really pay much attention to it.

    Good comment on global:: — Anders is really hesitant to introduce new keywords, for fear it would break existing code that uses it, since 1.x code can get promoted to run under .Net 2.0.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s