As mentioned in Chapter 2, all data types are identified by the combination of their namespace and their name. For the classes you defined earlier, there was no explicit namespace declaration. Classes such as these are automatically declared as members of the default global namespace. It is highly likely that such classes will experience a name collision, which occurs when you attempt to define two classes with the same name. Once you begin referencing other assemblies from third parties, the likelihood of a name collision increases even further.
To resolve this, you should place classes into namespaces. For example, classes outside of the System namespace are generally placed into a namespace corresponding with the company, product name, or both. Classes from Addison-Wesley, for example, are placed into an Awl or AddisonWesley namespace, and classes from Microsoft (not System classes) are located in the Microsoft namespace. You should use the namespace keyword to create a namespace and to assign a class to it, as shown in Listing 9.13.
Listing 9.13. Defining a Namespace
All content between the namespace declaration's curly brackets will then belong within the specified namespace. In Listing 9.13, Program is placed into the namespace AddisonWesley, making its full name AddisonWesley.Program. Optionally, C# allows a colon after the namespace name.
Like classes, namespaces support nesting. This provides for a hierarchical organization of classes. All the System classes relating to network APIs are in the namespace System.Net, for example, and those relating to the Web are in System.Web.
There are two ways to nest namespaces. The first way is to nest them within each other (similar to classes), as demonstrated in Listing 9.14.
Listing 9.14. Nesting Namespaces within Each Other
Such a nesting will assign the Program class to the AddisonWesley.Michaelis.EssentialCSharp namespace.
The second way is to use the full namespace in a single namespace declaration in which a period separates each identifier, as shown in Listing 9.15.
Listing 9.15. Nesting Namespaces Using a Period to Separate Each Identifier
Regardless of whether a namespace declaration follows Listing 9.14, Listing 9.15, or a combination of the two, the resulting CIL code will be identical. The same namespace may occur multiple times, in multiple files, and even across assemblies. For example, with the convention of one-to-one correlation between files and classes, you can define each class in its own file and surround it with the appropriate namespace declaration.
Namespace Alias Qualifier
Namespaces on their own deal with the vast majority of naming conflicts that might arise. However, sometimes (albeit rarely) conflict can arise because of an overlap in the namespace and class names. To account for this, the C# 2.0 compiler includes an option for providing an alias with the /reference option. For example, if the assemblies CoordinatesPlus.dll and Coordinates.dll have an overlapping type of Arc, you can reference both assemblies on the command line by assigning one or both references with a namespace alias qualifier that further distinguishes one class from the other. The results of such a reference appear in Output 9.7.
However, adding the alias during compilation is not sufficient on its own. In order to refer to classes in the aliased assembly, it is necessary to provide an extern directive that declares that the namespace alias qualifier is provided externally to the source code (see Listing 9.16).
Listing 9.16. Using the extern Alias Directive
Once the extern alias for CoordPlus appears, you can reference the namespace using CoordPlus, followed by either two colons or a period.
To ensure that the lookup for the type occurs in the global namespace, C# 2.0 allows items to have the global:: qualifier (but not global. because it could imaginably conflict with a real namespace of global).