As you have seen, namespaces provide a way of organizing related classes and other types. Unlike a file or a component, a namespace is a logical, rather than a physical, grouping. When you define a class in a C# file, you can include it within a namespace definition. Later, when you define another class that performs related work in another file, you can include it within the same namespace, creating a logical grouping that gives an indication to other developers using the classes they are related and used.:
Placing a type in a namespace effectively gives that type a long name, consisting of the type’s namespace as a series of names separated with periods ( . ), terminating with the name of the class. In the preceding example, the full name of the Subscriber struct is Customer Phone Book App. Subscriber. This allows distinct classes with the same short name to be used within the same program without ambiguity. This full name is often called the fully qualified name.
You can also nest namespaces within other namespaces, creating a hierarchical structure’ for your types:
Each namespace name is composed of the names of the namespaces it resides within, separated with periods, starting with the outermost namespace and ending with its own short name. So the full name for Thes rods arp namespace is Wrox. ProCSharp, and the full name of NamespaceExample class is Wrox.ProCSharp.Basics.NamespaceExample.
You can use this syntax to organize the namespaces in your namespace definitions too, so the previous code could also be written as follows:
Note that you are not permitted to declare a multipart namespace nested within another namespace.
The using Directive
Obviously, namespaces can grow rather long and tiresome to type, and the ability to indicate a particular class with such specificity why not always be necessary. Fortunately, as noted at the beginning of the chapter, C# allows you to abbreviate a class’s full name. To do this, list the class’s namespace at the top of the file, prefixed with the using keyword. Throughout the rest of the file, you can refer to the types in the namespace simply by their type names:
As remarked earlier, virtually all C# source code will have the statement using System; simply because so many useful classes supplied by Microsoft are contained in the System namespace.
If two namespaces referenced by using statements contain a type of the same name, you will need to use the full (or at least a longer) form of the name to ensure that the compiler knows which type is to be accessed. For example, say classes called NamespaceExample exist in both the Wrox. ProCSharp . Basics and Wrox. ProCSharp. OOPnamespaces. If you then create a class called Test in the Wrox. ProCSharp namespace, and instantiate one of the NamespaceExample classes in this ‘class, you need to specify which of these two classes you’re talking about:
Because using statements occur at the top of C# files, in the same place that C and C++ list #include statements, it’s easy for programmers moving from C++ to C# to confuse namespaces with C++-style heaper files. Don’t make this mistake. The using statement does no physical linking between files, and C# has no equivalent to C++ header files.
Your organization will probably want to spend some time developing a namespace schema so that its developers can quickly locate functionality that they need and so that the names of the organization’s homegrown classes won’t conflict with those in off-the-shelf class libraries. Guidelines on establishing your own namespace scheme along with other naming recommendations are discussed later in this chapter .
Another use of the using keyword is to assign aliases to classes and namespaces, If you have a very long namespace name that you want to refer to several times in your code but don’t want to include in a simple using statement (for example, to avoid type name conflicts), you can assign an alias to the namespace. The syntax for this is:
using.alias = NamespaceName;
The following example (a modified version of the previous example) assigns the alias Introduction to the Wrox. ProCSharp. Basics namespace and uses this to instantiate a NamespaceExample object, which is defined in this namespace. Notice the use of the namespace alias qualifier (: :). This forces the search to start with the Introduction namespace alias. If a class called Intro~uction had been introduced in the same scope, a conflict would happen. The : : operator allows the alias to be referenced even if the conflict exists. The NamespaceExample class has one method, GetNamespace ( ), which uses the GetType () method exposed by every class to access a Type object representing the class’s type. You use this object to return a name of the class’s namespace: