The C# classes that you design will be used by code that you write and possibly by code that
other people write. Your C# classes may be used by a VB.NET application or from within an
ASP.NET page. Moreover, your classes may very well be used alongside other classes
designed by other .NET developers.
Code written in a .NET language references classes by their names, and all of these classes
used together suggests an obvious dilemma: What happens if a developer wants to use two
classes that have the same name?
Suppose you write a C# class that reads records from a database and you name the class
Recordset. Code that wants to use your class may create objects as follows:
Recordset MyRecordset = new Recordset();
Now suppose that you package your classes into a .NET assembly and distribute your
assembly for use by other applications. Furthermore, suppose that someone obtains your
assembly and integrates it into his or her application. What happens if that same application
also makes use of another assembly written by someone else, which also contains a class
called Recordset? When the application code creates a new Recordset object, which class is
used to create the object: yours or the class in the other assembly?
This problem can be solved through the C# concept of name-spaces. Namespaces organize
classes under a named group, and the namespace name can be used to help distinguish
between two classes with the same name. Your C# code should use namespaces to help
further identify your classes under a common grouping, especially if you are planning to build
an assembly for use by other developers. Namespaces may even come in handy in C#
applications that you build, because your C# applications may use an external assembly that
uses class names which mirror yours.
Declaring a Namespace
You declare a namespace with the C# namespace keyword. A namespace identifier and curly
brackets follow the namespace keyword. Classes to be included in the namespace must be
declared within the namespace's curly brackets, as the shown in the following code:
namespace MyClasses
{
class MyFirstClass
{
}
}
This piece of code declares a class called MyFirstClass in a namespace called MyClasses.
Another developer may also write a class called MyFirstClass, but as long as the other
developer uses a different namespace name, the C# compiler finds the correct class to be used
for a particular statement.
You can declare a namespace within a namespace, if you wish. Simply enclose another
namespace declaration from within the first declaration:
namespace MyClasses
{
namespace MyInnerNamespace
{
class MyFirstClass
{
}
}
}
Tip It's generally a good idea to nest namespaces when you plan to offer more than one
distinct product in the form of classes. For example, Widget Corporation offers a
compression product and some terminal emulation routines. These namespaces would
then become Widget.Compression and Widget.Emulation, which group the products by
company but also keep them separated under the Widget namespace.
If you don't want to nest namespaces in this manner, you can achieve the same effect by
declaring both namespace declarations on the same statement and separating them with a
period, as follows:
namespace MyClasses.MyInnerNamespace
{
class MyFirstClass
{
}
}
The following types of declarations can appear in a namespace:
• Classes
• Structures
• Interfaces (see Chapter 13 for more information)
• Enumerations (see Chapter 14 for more information)
• Delegates (see Chapter 15 for more information)
Any type declaration not in this list results in compiler errors when you attempt to build your
application.
Declaring a Namespace in Multiple Source Files
The C# compiler enables you to use the same namespace name in multiple source files. It then
builds a binary file that combines all the classes into the same namespace.
Suppose, for example, that you want to build an assembly whose classes reside in a
namespace called MyAssembly. You want to write two classes for inclusion in that assembly
and you want to define the classes in separate files. You can simply re-use the namespace
name in both source files. The first source file can contain the declaration of the first class, as
follows:
namespace MyAssembly
{
class MyFirstClass
{
}
}
The second source file can contain the declaration of the second class and can use the same
namespace name:
namespace MyAssembly
{
class MySecondClass
{
}
}
When the two source files are built into a single assembly, the C# compiler builds an
assembly with a single namespace, MyAssembly, with two classes in the namespace.
This provides a benefit to you, the developer, should you want to separate certain
functionality into separate files or simply want to keep the length of each source file to a
minimum.
Using Classes in a Namespace
If you want to refer to a class in a specific namespace, you prefix the class name with the
name of its namespace:
MyClasses.MyFirstClass MyObject = new MyClasses.MyFirstClass();
Using this syntax helps you distinguish between classes in different code bases with the same
name. The C# compiler now has enough information to find the right class, because it also
knows what namespace to interrogate in order to find the class you are looking for.
If you are working with classes declared in nested namespaces, all namespace names must
appear when you refer to the class:
Namespace1.Namespace2.MyClass MyObject = new
Namespace1.Namespace2.MyClass();
Listing 12-1 illustrates the namespace concept.
Listing 12-1: Classes in Different Namespaces
namespace Namespace1
{
class TestClass
{
public TestClass()
{
System.Console.WriteLine("Hello from Namespace1.TestClass!");
}
}
}
namespace Namespace2
{
class TestClass
{
public TestClass()
{
System.Console.WriteLine("Hello from
Namespace2.TestClass!");
}
}
}
class MainClass
{
public static void Main()
{
Namespace1.TestClass Object1 = new Namespace1.TestClass();
Namespace2.TestClass Object2 = new Namespace2.TestClass();
}
}
The code in Listing 12-1 declares two classes called TestClass. The two class declarations are
in different namespaces, and the constructor for each class prints a message to the console.
The messages differ slightly so that you are able to tell which message came from which
class.
The Main() method in Listing 12-1 creates two objects: one of type Namespace1. TestClass
and one of type Namespace.TestClass. Because the constructors for the classes write
messages out to the console, running the code in Listing 12-1 results in the output shown in
Figure 12-1.
Figure 12-1: Referencing classes within namespaces
Note that the MainClass class in Listing 12-1 is not enclosed in a namespace declaration. This
is legal in C#. You do not have to enclose classes in namespace declarations. However,
classes that are not enclosed in namespaces cannot use the same name in another class defines
without a namespace.
If you need to use a class that is declared in a namespace, you must use its name- space name
when you use the class name. If you forget to do this, you get an error message from the C#
compiler. Suppose, for example, that the Main() method in Listing 12-1 tries to create an
object of class TestClass:
TestClass Object1 = new TestClass ();
The C# compiler cannot find a class called TestClass defined outside of a name- space, and it
issues the following error:
error CS0234: The type or namespace name 'TestClass' does not
exist in the class or namespace 'MainClass'
If you review the examples from previous chapters, you'll find that you've been using this
syntax all along in your calls to WriteLine(), as shown in the following example:
System.Console.WriteLine("Hello from C#!");
The WriteLine() method is in a class called Console, and the Console class is defined in a
.NET namespace called System.
Namespace Assistance with the using Keyword
You can use the C# keyword using in a variety of ways to make working with namespaces
easier, and save yourself a great deal of typing. At first sight, the using keyword resembles the
typical C/C++ directive #include. Don't let it fool you; the benefits are much more
empowering. The following sections describe some of these benefits.
Aliasing class names with the using keyword
Writing out fully qualified class names that include namespace identifiers can get a bit
tedious, especially if the names are long. You can use the using keyword to provide an aliased
name for the fully qualified class identifier, and you can use the alias name instead of the fully
qualified class identifier once the alias is established.
You can alias a name with a statement having the following structure:
• The using keyword
• The alias name
• An equals sign
• The fully qualified class name with the namespace identifier
• A statement terminating semicolon
Listing 12-2 adds to Listing 12-1 by aliasing the class names to shorter equivalents. The
shorter names are then used by the Main() method to work with objects of the classes.
Listing 12-2: Aliasing Class Names
using Class1 = Namespace1.TestClass;
using Class2 = Namespace2.TestClass;
namespace Namespace1
{
class TestClass
{
public TestClass()
{
System.Console.WriteLine("Hello from
Namespace1.TestClass!");
}
}
}
namespace Namespace2
{
class TestClass
{
public TestClass()
{
System.Console.WriteLine("Hello from
Namespace2.TestClass!");
}
}
}
class MainClass
{
public static void Main()
{
Class1 Object1 = new Class1();
Class2 Object2 = new Class2();
}
}
As with the previous example, Listing 12-2 outputs the same messages you have previously
seen. You can see these results in Figure 12-2.
Figure 12-2: Aliasing class names
The using statements must appear in the source code before the namespaces themselves are
declared. If the using statements appear after namespace declarations, you receive the
following error message from the C# compiler:
error CS1529: A using clause must precede all other namespace elements
In Chapter 7, you see that the C# keywords defining variable types are actually structures
defined by the .NET Framework. Take another look at Table 7-1 and notice the following:
• The value type structures reside in the .NET System namespace.
• The using keyword is used to alias the .NET structure names to the equivalent C#
keywords. You may imagine Table 7-1 being implemented within the .NET
Framework using C# statements such as the following:
• using sbyte = System.SByte;
• using byte = System.Byte;
• using short = System.Int16;
// ... more declarations ...
You can alias namespace names as well as classes, as shown in Listing 12-3.
Listing 12-3: Aliasing Namespace Names
using N1 = Namespace1;
using N2 = Namespace2;
namespace Namespace1
{
class TestClass
{
public TestClass()
{
System.Console.WriteLine("Hello from
Namespace1.TestClass!");
}
}
}
namespace Namespace2
{
class TestClass
{
public TestClass()
{
System.Console.WriteLine("Hello from
Namespace2.TestClass!");
}
}
}
class MainClass
{
public static void Main()
{
N1.TestClass Object1 = new N1.TestClass();
N2.TestClass Object2 = new N2.TestClass();
}
}
Declaring namespace directives with the using keyword
If you use a class declared in a namespace, you must prefix the class name with the
namespace name, even if you aren't working with any other namespaces that may have a class
with the same name. This is why the examples used until now have always called WriteLine()
with the System namespace qualifier:
System.Console.WriteLine("Hello from C#!");
By default, forgetting to use the namespace name causes the C# compiler to issue an error:
error CS0234: The type or namespace name 'Console' does not
exist in the class or namespace 'Namespace1'
Prefixing every class name with namespace names like System gets tedious, especially if you
need to do it many times. Fortunately, you can use the using keyword to help reduce your
coding time.
Using the using keyword with a namespace name tells the C# compiler that you want to refer
to classes in the named namespace without prefixing the class names with the namespace
name. For example, take a look at the following statement:
using System;
This is called a namespace directive. Namespace directives tell the C# compiler that the code
will be using classes from the namespace and that the classes won't be prefixed with the
namespace name. The C# compiler does the work of finding the definition of each class in
one of the namespaces referenced in a namespace directive.
Listing 12-4 is a modification of Listing 12-2; it includes a using statement that references the
.NET System namespace.
Listing 12-4: Using a Namespace Directive
using System;
using Class1 = Namespace1.TestClass;
using Class2 = Namespace2.TestClass;
namespace Namespace1
{
class TestClass
{
public TestClass()
{
Console.WriteLine("Hello from
Namespace1.TestClass!");
}
}
}
namespace Namespace2
{
class TestClass
{
public TestClass()
{
Console.WriteLine("Hello from
Namespace2.TestClass!");
}
}
}
class MainClass
{
public static void Main()
{
Class1 Object1 = new Class1();
Class2 Object2 = new Class2();
}
}