C# 命名空间9_c
C# 命名空间9由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“c”。
命名空间.................................................................................................................................................................2 9.1 编译单元......................................................................................................................................................2 9.2 命名空间声明..............................................................................................................................................2 9.3 using 指令.....................................................................................................................................................3 9.3.1 Using 别名指令.....................................................................................................................................4 9.3.2 Using 命名空间指令.............................................................................................................................6 9.4 命名空间成员..............................................................................................................................................8 9.5 类型声明......................................................................................................................................................9
1.命名空间
C# 程序是利用命名空间组织起来的。命名空间既用作程序的“内部”组织系统,也用作“外部”组织系统(一种向其他程序公开自己拥有的程序元素的方法)。using 指令(第 1.3 节)是用来使命名空间用起来更方便。
1.1 编译单元
compilation-unit 定义了源文件的总体结构。编译单元的组成方式如下:先是零个或多个 using-directive,后跟零个或多个 global-attributes,然后是零个或多个 namespace-member-declaration。
compilation-unit: using-directivesopt
global-attributesopt
namespace-member-declarationsopt
一个 C# 程序由一个或多个编译单元组成,每个编译单元都用一个单独的源文件来保存。编译 C# 程序时,所有这些编译单元一起进行处理。因此,这些编译单元间可以互相依赖,甚至以循环方式互相依赖。
一个编译单元中的 using-directives 影响该编译单元内的 global-attributes 和 namespace-member-declarations,但是不会影响其他编译单元。
编译单元的 global-attributes(第 错误!未找到引用源。章)允许指定目标程序集和模块的属性。程序集和模块充当类型的物理容器。程序集可以包含若干个在物理上分离的模块。一个程序中各编译单元中的 namespace-member-declarations 用于为一个称为“全局命名空间”的单个声明空间提供成员。例如:
文件 A.cs:
cla A {} 文件 B.cs:
cla B {} 这两个编译单元是为该全局命名空间提供成员的,在本例中它们分别声明了具有完全限定名 A 和 B 的两个类。由于这两个编译单元为同一声明空间提供成员,因此如果它们分别包含了一个同名成员的声明,将会是个错误。
1.2 命名空间声明
一个 namespace-declaration 的组成方式如下:先是关键字 namespace,后跟一个命名空间名称和体,然后加一个分号(可选)。
namespace-declaration: namespace
qualified-identifier
namespace-body
;opt
qualified-identifier: identifier qualified-identifier
.identifier namespace-body: {
using-directivesopt
namespace-member-declarationsopt
}
namespace-declaration 可以作为顶级声明出现在 compilation-unit 中,或是作为成员声明出现在另一个 namespace-declaration 内。当 namespace-declaration 作为顶级声明出现在 compilation-unit 中时,该命名空间成为全局命名空间的一个成员。当一个 namespace-declaration 出现在另一个 namespace-declaration 内时,该内部命名空间就成为包含着它的外部命名空间的一个成员。无论是何种情况,一个命名空间的名称在它所属的命名空间内必须是唯一的。
命名空间隐式地为 public,而且在命名空间的声明中不能包含任何访问修饰符。在 namespace-body 内,可选用 using-directives 来导入其他命名空间和类型的名称,这样,就可以直接地而不是通过限定名来引用它们。可选的 namespace-member-declarations 用于为命名空间的声明空间提供成员。请注意,所有的 using-directives 都必须出现在任何成员声明之前。
namespace-declaration 中的 qualified-identifier 可以是单个标识符或者是由“.”标记分隔的标识符序列。后一种形式允许一个程序直接定义一个嵌套命名空间,而不必按词法嵌套若干个命名空间声明。例如,namespace N1.N2 { cla A {} cla B {} } 在语义上等效于
namespace N1 { namespace N2 {
} } cla A {} cla B {} 命名空间是可扩充的,两个具有相同的完全限定名的命名空间声明是在为同一声明空间(第 错误!未找到引用源。节)提供成员。在下面的示例中
namespace N1.N2 { cla A {} } namespace N1.N2 { cla B {} } 上面的两个命名空间声明为同一声明空间提供了成员,在本例中它们分别声明了具有完全限定名 N1.N2.A 和 N1.N2.B 的两个类。由于两个声明为同一声明空间提供成员,因此如果它们分别包含一个同名成员的声明,就将出现错误。
1.3 using 指令
using 指令(using directives)方便了对在其他命名空间中定义的命名空间和类型的使用。using 指令影响 namespace-or-type-name(第 错误!未找到引用源。节)和 simple-name(第 7.5.2 节)的名称解析过程,与声明不同,using 指令不会向在其中使用它们的编译单元或命名空间的基础声明空间中提供新成员。
using-directives: using-directive using-directives
using-directive using-directive: using-alias-directive using-namespace-directive using-alias-directive(第 1.3.1 节)用于为一个命名空间或类型引入一个别名。using-namespace-directive(第 1.3.2 节)用于导入一个命名空间的类型成员。
using-directive 的范围扩展到直接包含它的编译单元或命名空间体内的所有 namespace-member-declarations。具体而言,using-directive 的范围不包括与它对等的 using-directive。因此,对等 using-directive 互不影响,而且按什么顺序编写它们也无关紧要。
1.3.1 Using 别名指令
using-alias-directive 为一个命名空间或类型(在直接包含该指令的编译单元或命名空间体内)引入用作别名的标识符。
using-alias-directive: using
identifier
=
namespace-or-type-name
;在包含 using-alias-directive 的编译单元或命名空间体内的成员声明中,由 using-alias-directive 引入的标识符可用于引用给定的命名空间或类型。例如:
namespace N1.N2 { cla A {} } namespace N3 { using A = N1.N2.A;cla B: A {} } 上面的示例中,在 N3 命名空间中的声明成员内,A 是 N1.N2.A 的别名,因此类 N3.B 从类 N1.N2.A 派生。通过为 N1.N2 创建别名 R 然后引用 R.A 可以得到同样的效果:
namespace N3 { using R = N1.N2;cla B: R.A {} } using-alias-directive 中的 identifier 在直接包含该 using-alias-directive 的编译单元或命名空间的声明空间内必须是唯一的。例如: namespace N3 { cla A {} } namespace N3 { using A = N1.N2.A;}
// Error, A already exists 上例中,N3 已包含了成员 A,因此 using-alias-directive 使用 A 作标识符会导致一个编译时错误。同样,如果同一个编译单元或命名空间体中的两个或更多 using-alias-directive 用相同名称声明别名,也会导致一个编译时错误。
using-alias-directive 使别名可用在特定编译单元或命名空间体内,但是它不会向基础声明空间提供任何新成员。换句话说,using-alias-directive 是不可传递的,它仅影响它在其中出现的编译单元或命名空间体。在下面的示例中
namespace N3 { using R = N1.N2;} namespace N3 { cla B: R.A {} }
// Error, R unknown 引入 R 的 using-alias-directive 的范围只延伸到包含它的命名空间体中的成员声明,因此 R 在第二个命名空间声明中是未知的。但是,如果将 using-alias-directive 放置在包含它的编译单元中,则该别名在两个命名空间声明中都可用:
using R = N1.N2;namespace N3 { cla B: R.A {} } namespace N3 { cla C: R.A {} } 和常规成员一样,using-alias-directive 引入的别名在嵌套范围中也可被具有相似名称的成员所隐藏。在下面的示例中
using R = N1.N2;namespace N3 { cla R {} cla B: R.A {} }
// Error, R has no member A B 的声明中对 R.A 的引用将导致编译时错误,原因是这里的 R 所引用的是 N3.R 而不是 N1.N2。
编写 using-alias-directive 的顺序并不重要,对在 using-alias-directive 引用的 namespace-or-type-name 的解析过程既不受 using-alias-directive 本身影响,也不受直接包含着该指令的编译单元或命名空间体中的其他 using-directive 影响。换句话说,对 using-alias-directive 的 namespace-or-type-name 的解析,就如同在直接包含该指定的编译单元或命名空间体中根本没有 using-directive 一样来处理。在下面的示例中
namespace N1.N2 {} namespace N3 { using R1 = N1;
// OK using R2 = N1.N2;using R3 = R1.N2;}
// OK
// Error, R1 unknown 最后一个 using-alias-directive 导致编译时错误,原因是它不受第一个 using-alias-directive 的影响。
using-alias-directive 可以为任何命名空间或类型创建别名,包括它在其中出现的命名空间本身,以及嵌套在该命名空间中的其他任何命名空间或类型。
对一个命名空间或类型进行访问时,无论用它的别名,还是用它的所声明的名称,结果是完全相同的。例如,给定
namespace N1.N2 { cla A {} } namespace N3 { using R1 = N1;using R2 = N1.N2;cla B {
} } N1.N2.A a;R1.N2.A b;R2.A c;
// refers to N1.N2.A // refers to N1.N2.A
// refers to N1.N2.A 名称 N1.N2.A、R1.N2.A 和 R2.A 是等效的,它们都引用完全限定名为 N1.N2.A 的类。
1.3.2 Using 命名空间指令
using-namespace-directive 将一个命名空间中所包含的类型导入到直接包含该指定的编译单元或命名空间体中,从而可以直接使用每个被导入的类型的标识符而不必加上它们的限定名。
using-namespace-directive: using
namespace-name
;在包含 using-namespace-directive 的编译单元或命名空间体中的成员声明内,可以直接引用包含在给定命名空间中的那些类型。例如:
namespace N1.N2 { cla A {} } namespace N3 { using N1.N2;cla B: A {} } 上面的示例中,在 N3 命名空间中的成员声明内,N1.N2 的类型成员是直接可用的,所以类 N3.B 从类 N1.N2.A 派生。
using-namespace-directive 导入包含在给定命名空间中的类型,但要注意,它不导入嵌套的命名空间。在下面的示例中
namespace N1.N2 { cla A {} } namespace N3 { using N1;cla B: N2.A {} }
// Error, N2 unknown using-namespace-directive 导入包含在 N1 中的类型,但是不导入嵌套在 N1 中的命名空间。因此,在 B 的声明中引用 N2.A 导致编译时错误,原因是在涉及的范围内没有名为 N2 的成员。
与 using-alias-directive 不同,using-namespace-directive 可能导入一些类型,它们的标识符在包含该指令的编译单元或命名空间体内已被定义。事实上,using-namespace-directive 导入的名称会被包含该指令的编译单元或命名空间体中具有类似名称的成员所隐藏。例如:
namespace N1.N2 { cla A {} cla B {} } namespace N3 { using N1.N2;cla A {} } 此处,在 N3 命名空间中的成员声明内,A 引用 N3.A 而不是 N1.N2.A。
当由同一编译单元或命名空间体中的 using-namespace-directive 导入多个命名空间时,如果它们所包含的类型中有重名的,则直接引用该名称就被认为是不明确的。在下面的示例中
namespace N1 { cla A {} } namespace N2 { cla A {} } namespace N3 { using N1;using N2;cla B: A {} } N1 和 N2 都包含一个成员 A,而由于 N3 将两者都导入,所以在 N3 中引用 A 会导致一
// Error, A is ambiguous 个编译时错误。这种情况的冲突,有两种解决办法:使用限定名来引用 A,或者利用 using-alias-directive 为想要引用的某个特定的 A 引入一个别名。例如:
namespace N3 { using N1;using N2;using A = N1.A;cla B: A {} }
// A means N1.A 同 using-alias-directive 一样,using-namespace-directive 不会向编译单元或命名空间的基础声明空间提供任何新成员,因而,它仅影响它出现在的编译单元或者命名空间体。
对 using-namespace-directive 所引用的 namespace-name 的解析方式,与对 using-alias-directive 所引用的 namespace-or-type-name 的解析方式相同。因此,同一编译单元或命名空间体中的 using-namespace-directive 互不影响,而且可以按照任何顺序编写。
1.4 命名空间成员
namespace-member-declaration 或是一个 namespace-declaration(第 1.2 节),或是一个 type-declaration(第 9.5 节)。
namespace-member-declarations: namespace-member-declaration namespace-member-declarations
namespace-member-declaration namespace-member-declaration: namespace-declaration type-declaration 编译单元或命名空间体可以包含 namespace-member-declarations,而此类声明则为与包含它们的编译单元或命名空间体的基础声明空间提供新成员。
1.5 类型声明
type-declaration 是 cla-declaration(第 错误!未找到引用源。节)、struct-declaration(第 错误!未找到引用源。节)、interface-declaration(第 错误!未找到引用源。节)、enum-declaration(第 错误!未找到引用源。节)或 delegate-declaration(第 错误!未找到引用源。节)。
type-declaration: cla-declaration struct-declaration interface-declaration enum-declaration delegate-declaration type-declaration 可以作为顶级声明出现在编译单元中,或者作为成员声明出现在命名空间、类或结构内部。
当类型 T 的类型声明作为编译单元中的顶级声明出现时,新声明的类型的完全限定名正好是 T。当类型 T 的类型声明出现在命名空间、类或结构内时,新声明的类型的完全限定名是 N.T,其中 N 是包含它的命名空间、类或结构的完全限定名。
在类或结构内声明的类型称为嵌套类型(第 错误!未找到引用源。节)。在一个类型声明中允许使用哪些访问修饰符以及具有何种默认访问属性,依赖于该声明发生处的上下文(第 错误!未找到引用源。节):
在编译单元或命名空间中声明的类型可以具有 public 或 internal 访问属性。默认为 internal 访问属性。 在类中声明的类型可以具有 public、protected internal、protected、internal 或 private 访问属性。默认为 private 访问属性。 在结构中声明的类型可以具有 public、internal 或 private 访问属性。默认为
private 访问属性。