A namespace is a domain within which type names must be unique. Types are typically organized
into hierarchical namespaces—both to
avoid naming conflicts and to make type names easier to find. For example,
the RSA
type that handles public key
encryption is defined within the following namespace:
System.Security.Cryptography
A namespace forms an integral part of a type’s name. The following
code calls RSA
’s Create
method:
System.Security.Cryptography.RSA rsa = System.Security.Cryptography.RSA.Create();
Namespaces are independent of assemblies, which are units of deployment such as an .exe or .dll.
Namespaces also have no impact on member accessibility: public
, internal
, private
, and so on.
The namepace
keyword defines a namespace for types within that block. For
example:
namespace Outer.Middle.Inner { class Class1 {} class Class2 {} }
The dots in the namespace indicate a hierarchy of nested namespaces. The code that follows is semantically identical to the preceding example.
namespace Outer { namespace Middle { namespace Inner { class Class1 {} class Class2 {} } } }
You can refer to a type with its fully qualified
name, which includes all namespaces from the outermost to the
innermost. For example, we could refer to Class1
in the preceding example as Outer.Middle.Inner.Class1
.
Types not defined in any namespace are said to reside in the
global namespace. The global namespace also includes
top-level namespaces, such as Outer
in
our example.
The using
directive imports a namespace and is
a convenient way to refer to types without their fully qualified names.
For example, we can refer to Class1
in the preceding example as follows:
using Outer.Middle.Inner; class Test // Test is in the global namespace { static void Main() { Class1 c; // Don't need fully qualified name ... } }
A using
directive can be nested
within a namespace itself, to limit the scope of the directive.
Names declared in outer namespaces can be used unqualified
within inner namespaces. In this example, the names Middle
and Class1
are implicitly imported into Inner
:
namespace Outer
{
namespace Middle
{
class Class1 {}
namespace Inner
{
class Class2 : Class1
{}
}
}
}
If you want to refer to a type in a different branch of your
namespace hierarchy, you can use a partially qualified name. As you can see in the following example, we base
Sales
Report
on Common.ReportBase
:
namespace MyTradingCompany
{
namespace Common
{
class ReportBase {}
}
namespace ManagementReporting
{
class SalesReport : Common.ReportBase
{}
}
}
If the same type name appears in both an inner and outer namespace, the inner name wins. To refer to the type in the outer namespace, you must qualify its name.
All type names are converted to fully qualified names at compile time. Intermediate Language (IL) code contains no unqualified or partially qualified names.
Importing a namespace can result in type-name collision. Rather than importing the whole namespace, you can import just the specific types you need, giving each type an alias. For example:
using PropertyInfo2 = System.Reflection.PropertyInfo; class Program { PropertyInfo2 p; }
An entire namespace can be aliased, as follows:
using R = System.Reflection; class Program { R.PropertyInfo p; }