4.6 命名空间
知识点讲解:光盘:视频\PPT讲解(知识点)\第4章\命名空间.mp4
在C#开发应用中,通常将应用程序放到一个命名空间中。命名空间保存的是一个完整的C#程序,里面的程序是完全独立存在的。
4.6.1 编译单元
C#的编译单元定义了源文件的总体结构。一个C#程序是由一个或多个编译单元组成的,每个编译单元都用独立的源文件来保存。编译C#程序时,所有这些编译单元一起进行处理。因此,这些编译单元间可以互相依赖,甚至以循环方式互相依赖。
如果一个程序包含多个源文件,编译程序时则需要将所有的源文件放在一起编译,其语法格式如下。
csc <source 文件名> <source文件名> ... <source文件名>
使用如下的命令可以显示csc的所有参数的意义。
csc/?
使用Visual Studio则可以迅速地创建一个项目,并能将所有的源文件都放在项目中。
为了最大限度地避免类名冲突,C#使用命名空间来组织类。具体的使用原则如下。
- 在同一个命名空间中,类名不能重名。
- 在不同的命名空间中,可以使用相同的类名。
一个编译单元可以包括任意个命名空间定义,也可能没有。命名空间是可以嵌套的,即在一个命名空间内部还可以定义其他的命名空间。
命名空间声明可以作为顶级声明出现在编译单元中,或者作为成员声明出现在另一个命名空间声明内。当命名空间声明作为顶级声明出现在编译单元中时,该命名空间成为全局命名空间的一个成员。当某个命名空间声明出现在另一个命名空间声明内时,该内部命名空间就成为包含着它的外部命名空间的一个成员。无论是哪种情况,一个命名空间的名称在它所属的命名空间内必须是唯一的。
在C#中,命名空间使用关键字namespace来声明,语法格式如下。
namespace 命名空间名{
using指令
代码块
}
命名空间的隐式关键字是public,而且在命名空间的声明中不能包含任何访问修饰符。
在代码块中,可选用零个或者多个using指令来导入其他命名空间和类型的名称,这样就可以直接地而不是通过限定名来引用它们。
命名空间名称可以是单个标识符或者是由“.”标记分隔的标识符序列。后一种形式允许一个程序直接定义一个嵌套命名空间,而不必按词法嵌套若干个命名空间声明。例如,下面的两段代码的功能是等效的。
namespace mm.nn{
class A {}
class B {}
}
namespace mm
{
namespace nn
{
class A {}
class B {}
}
}
4.6.2 完全限定名标识
每个命名空间和类型都具有一个完全限定名,该名称在所有其他命名空间或类型中唯一标识该命名空间或类型。假如存在命名空间mm和类型mm,则两者的完全限定名需要遵循如下规则。
- 如果mm是全局命名空间的成员,则它的完全限定名为mm。
- 如果mm不是全局命名空间的成员,它的完全限定名为A.mm,其中A声明了mm的命名空间或类型的完全限定名。
因为命名空间或类型的每个成员都必须具有唯一的名称,因此,如果将这些成员名称置于命名空间或类型的完全限定名之后,这样构成的成员完全限定名肯定符合唯一性。例如在下面的代码中,演示了多命名空间和类型声明及其关联的完全限定名。
class mm {}
namespace aa {
class nn
{
class C {}
}
namespace zz
{
class D {}
}
}
namespace aa.nn
{
class E {}
}
4.6.3 using指令
在C#程序中,使用using指令简化了对在其他命名空间中定义的命名空间和类型的使用步骤。using指令能够影响命名空间或者类型名称的解析过程,但是不会声明为任何类型。为此,using指令不会在使用它们的编译单元或命名空间中定义新成员。
在C#中,使用using指令的语法格式如下。
using命名空间名;
命名空间名称可以是单个标识符或者是由“.”标记分隔的标识符序列。using指令将“命名空间名”所标识的命名空间内的类型成员导入当前编译单元中,从而可以直接使用每个被导入的类型的标识符,而不必加上它们的完全限定名。
C#中using指令的主要特点如下。
(1)在包含using指令的编译单元或命名空间中的成员声明内,可以直接引用包含在给定命名空间中的那些类型。
(2)using指令能够导入包含在给定的命名空间中的类型,但是不能导入该命名空间所嵌套的命名空间。
(3)using指令还可以使用指定别名的形式,语法格式如下。
using别名=命名空间或类型名;
(4)using指令中的“别名”标识符在如下条件时必须是唯一的。
- 直接包含该using指令的编译单元。
- 在命名空间的声明空间内。
例如下面的一段代码。
namespace N3 {
class A {}
}
namespace N3
{
using A = N1.N2.A;
}
在上述代码中,class A是可行的,因为A已经定义在命名空间N3中;但是“using A = N1.N2.A”是非法的,因为A已经存在于命名空间N3中。
(5)using指令指定的别名是不可传递的,它仅影响使用它的编译单元或命名空间,而不会影响具有相同限定名的命名空间。
(6)using指令的顺序并不重要。using指令可以为任何命名空间或类型创建别名,包括它所处的命名空间,以及嵌套在该命名空间中的其他任何命名空间或类型。
(7)对一个命名空间或类型进行访问时,无论用它的别名,还是用它声明的名称,最终结果是完全相同的。
(8)C#内的using指令导入的名称会被如下元素隐藏。
- 包含该指令的编译单元。
- 命名空间中具有相同名称的成员。