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:
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
#ifUSE_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::
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
“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?
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.