Friday, April 25, 2008

Notes On the :: Operator in C#

Have you seen this construct before in auto-generated partial classes (e.g. code-behind .designer.cs for a web control)?

protected global::System.Web.UI.WebControls.TextBox MyTextBox;

Basically it's there to ensure that the System namespace is the same System namespace that's declared in the global namespace. So, why would they need this? Consider that you might define your new UserControl -derived class in a namespace like this:

namespace MyNamespace.System { ... }

Visual Studio's code-generator would create a partial class in the MyNamespace.System namespace, in which it would define a field MyTextBox of type System.Web.UI.WebControls.TextBox. However, when the time came for the compiler to put the puzzle together, the namespace resolution rules would match the "System" part of the member's type to the [unintended] "MyNamespace.System" namespace. Not cool.

Enter the global namespace alias, and the namespace alias qualifier operator. (Wow, that sentence is a mouthful).

To force the compiler to use the intended "System" namespace (which resides in the global namespace, not the MyNamespace namespace), the MyTextBox member is declared with the global:: namespace alias qualifier.

Obviously, things NOT to do include:
1) using global = System.Diagnostics;
Generates the compiler warning: Defining an alias named 'global' is ill-advised since 'global::' always references the global namespace and not an alias.
2) namespace System { class MyClass { } }
No warning from the compiler (Java doesn't let you do the equivalent).

Further usage patterns:

using sys = global::System; //<-- nice and recursive :-)
using diag = System.Diagnostics;
using dbg = System.Diagnostics.Debug;

sys::Object o = new System.Object();
diag::Debug.Assert(true); // <-- OK
dbg.Assert(true); // <-- OK, but important to make the distinction that it's a "type" alias and not a "namespace" alias.