命名空间Namespaces

C # 程序使用命名空间进行组织。C# programs are organized using namespaces. 命名空间同时用作程序的 "内部" 组织系统和 "外部" 组织系统,这是一种用于提供向其他程序公开的程序元素的方式。Namespaces are used both as an "internal" organization system for a program, and as an "external" organization system—a way of presenting program elements that are exposed to other programs.

使用 指令 (使用指令) 提供以简化命名空间的使用。Using directives (Using directives) are provided to facilitate the use of namespaces.

编译单元Compilation units

Compilation_unit 定义源文件的整体结构。A compilation_unit defines the overall structure of a source file. 一个编译单元由零个或多个 using_directive,后跟零个或多个 global_attributes 再后跟零个或多个 namespace_member_declarationA compilation unit consists of zero or more using_directive s followed by zero or more global_attributes followed by zero or more namespace_member_declaration s.

compilation_unit
    : extern_alias_directive* using_directive* global_attributes? namespace_member_declaration*
    ;

C # 程序包含一个或多个编译单元,每个单元包含在单独的源文件中。A C# program consists of one or more compilation units, each contained in a separate source file. 在编译 c # 程序时,将一起处理所有编译单元。When a C# program is compiled, all of the compilation units are processed together. 因此,编译单元可能以循环方式相互依赖。Thus, compilation units can depend on each other, possibly in a circular fashion.

编译单元的 using_directive 会影响该编译单元的 global_attributesnamespace_member_declaration,但不会对其他编译单元产生任何影响。The using_directive s of a compilation unit affect the global_attributes and namespace_member_declaration s of that compilation unit, but have no effect on other compilation units.

编译单元的 global_attributes (属性) 允许目标程序集和模块的属性规范。The global_attributes (Attributes) of a compilation unit permit the specification of attributes for the target assembly and module. 程序集和模块充当类型的物理容器。Assemblies and modules act as physical containers for types. 程序集可以由多个物理上独立的模块组成。An assembly may consist of several physically separate modules.

程序的每个编译单元的 namespace_member_declaration 将成员分配到称为全局命名空间的单个声明空间。The namespace_member_declaration s of each compilation unit of a program contribute members to a single declaration space called the global namespace. 例如:For example:

文件 A.csFile A.cs:

class A {}

文件 B.csFile B.cs:

class B {}

这两个编译单元向单一全局命名空间贡献,在本例中,用完全限定的名称和声明两个类 A BThe two compilation units contribute to the single global namespace, in this case declaring two classes with the fully qualified names A and B. 因为这两个编译单元导致相同的声明空间,所以如果每个单元都包含具有相同名称的成员的声明,则会出现错误。Because the two compilation units contribute to the same declaration space, it would have been an error if each contained a declaration of a member with the same name.

命名空间声明Namespace declarations

Namespace_declaration 包含关键字 namespace ,后跟命名空间名称和正文,可选择后跟一个分号。A namespace_declaration consists of the keyword namespace, followed by a namespace name and body, optionally followed by a semicolon.

namespace_declaration
    : 'namespace' qualified_identifier namespace_body ';'?
    ;

qualified_identifier
    : identifier ('.' identifier)*
    ;

namespace_body
    : '{' extern_alias_directive* using_directive* namespace_member_declaration* '}'
    ;

Namespace_declaration 可以作为顶级声明出现在 compilation_unit 中,或作为另一个 namespace_declaration 中的成员声明出现。A namespace_declaration may occur as a top-level declaration in a compilation_unit or as a member declaration within another namespace_declaration. 如果 namespace_declaration 作为 compilation_unit 中的顶级声明出现,则命名空间将成为全局命名空间的成员。When a namespace_declaration occurs as a top-level declaration in a compilation_unit, the namespace becomes a member of the global namespace. 如果 namespace_declaration 在另一个 namespace_declaration 中发生,则内部命名空间将成为外部命名空间的成员。When a namespace_declaration occurs within another namespace_declaration, the inner namespace becomes a member of the outer namespace. 在任一情况下,命名空间的名称在包含命名空间中必须是唯一的。In either case, the name of a namespace must be unique within the containing namespace.

命名空间是隐式的 public ,并且命名空间的声明不能包含任何访问修饰符。Namespaces are implicitly public and the declaration of a namespace cannot include any access modifiers.

namespace_body 中,可选 using_directive 导入其他命名空间、类型和成员的名称,从而允许直接引用这些命名空间,而不是通过限定名称引用。Within a namespace_body, the optional using_directive s import the names of other namespaces, types and members, allowing them to be referenced directly instead of through qualified names. 可选 namespace_member_declaration 将成员附加到命名空间的声明空间。The optional namespace_member_declaration s contribute members to the declaration space of the namespace. 请注意,所有 using_directive 必须出现在任何成员声明之前。Note that all using_directive s must appear before any member declarations.

Namespace_declarationqualified_identifier 可以是单个标识符,也可以是由 "" 标记分隔的标识符序列 .The qualified_identifier of a namespace_declaration may be a single identifier or a sequence of identifiers separated by "." tokens. 后一种形式允许程序定义嵌套命名空间,而无需在词法上嵌套若干命名空间声明。The latter form permits a program to define a nested namespace without lexically nesting several namespace declarations. 例如,For example,

namespace N1.N2
{
    class A {}

    class B {}
}

在语义上等效于is semantically equivalent to

namespace N1
{
    namespace N2
    {
        class A {}

        class B {}
    }
}

命名空间是开放式的,并且两个具有相同完全限定名称的命名空间声明在) (声明 的声明空间。Namespaces are open-ended, and two namespace declarations with the same fully qualified name contribute to the same declaration space (Declarations). 示例中In the example

namespace N1.N2
{
    class A {}
}

namespace N1.N2
{
    class B {}
}

上面的两个命名空间声明为同一声明空间提供了一个,在此示例中,声明了两个具有完全限定名称和的类 N1.N2.A N1.N2.Bthe two namespace declarations above contribute to the same declaration space, in this case declaring two classes with the fully qualified names N1.N2.A and N1.N2.B. 由于这两个声明会影响到相同的声明空间,因此,如果每个声明都包含具有相同名称的成员的声明,则会出现错误。Because the two declarations contribute to the same declaration space, it would have been an error if each contained a declaration of a member with the same name.

外部别名Extern aliases

Extern_alias_directive 引入了一个标识符,用作命名空间的别名。An extern_alias_directive introduces an identifier that serves as an alias for a namespace. 别名命名空间的规范是程序源代码的外部,并且还适用于别名命名空间的嵌套命名空间。The specification of the aliased namespace is external to the source code of the program and applies also to nested namespaces of the aliased namespace.

extern_alias_directive
    : 'extern' 'alias' identifier ';'
    ;

Extern_alias_directive 的作用域扩展到其直接包含编译单元或命名空间正文的 using_directive s、 global_attributesnamespace_member_declarationThe scope of an extern_alias_directive extends over the using_directive s, global_attributes and namespace_member_declaration s of its immediately containing compilation unit or namespace body.

在包含 extern_alias_directive 的编译单元或命名空间体内, extern_alias_directive 引入的标识符可用于引用化名命名空间。Within a compilation unit or namespace body that contains an extern_alias_directive, the identifier introduced by the extern_alias_directive can be used to reference the aliased namespace. 标识符 是单词的编译时错误 globalIt is a compile-time error for the identifier to be the word global.

Extern_alias_directive 使别名在特定编译单元或命名空间体中可用,但不会将任何新成员分配给基础声明空间。An extern_alias_directive makes an alias available within a particular compilation unit or namespace body, but it does not contribute any new members to the underlying declaration space. 换句话说, extern_alias_directive 是不可传递的,而是只影响它发生的编译单元或命名空间体。In other words, an extern_alias_directive is not transitive, but, rather, affects only the compilation unit or namespace body in which it occurs.

下面的程序声明并使用两个 extern 别名 XY 每个别名都表示不同命名空间层次结构的根:The following program declares and uses two extern aliases, X and Y, each of which represent the root of a distinct namespace hierarchy:

extern alias X;
extern alias Y;

class Test
{
    X::N.A a;
    X::N.B b1;
    Y::N.B b2;
    Y::N.C c;
}

该程序声明了 extern 别名和的存在 X Y ,但别名的实际定义是程序外部的。The program declares the existence of the extern aliases X and Y, but the actual definitions of the aliases are external to the program. N.B现在,可以 X.N.B Y.N.B 使用命名空间别名限定符和将同名类引用为、或 X::N.B Y::N.BThe identically named N.B classes can now be referenced as X.N.B and Y.N.B, or, using the namespace alias qualifier, X::N.B and Y::N.B. 如果程序声明未提供任何外部定义的 extern 别名,则会发生错误。An error occurs if a program declares an extern alias for which no external definition is provided.

using 指令Using directives

*使用指令 _ 有助于使用其他命名空间中定义的命名空间和类型。*Using directives _ facilitate the use of namespaces and types defined in other namespaces. 使用指令会影响 _namespace_or_type_name * s (命名空间和类型名称) 和 simple_name (简单名称) 的名称解析过程,但不同的是,使用指令不会将新成员分配给编译单元的基础声明空间或使用它们的命名空间。Using directives impact the name resolution process of _namespace_or_type_name*s (Namespace and type names) and simple_name s (Simple names), but unlike declarations, using directives do not contribute new members to the underlying declaration spaces of the compilation units or namespaces within which they are used.

using_directive
    : using_alias_directive
    | using_namespace_directive
    | using_static_directive
    ;

使用别名指令Using_alias_directive () 引入命名空间或类型的别名。A using_alias_directive (Using alias directives) introduces an alias for a namespace or type.

Using_namespace_directive (使用命名空间指令) 导入命名空间的类型成员。A using_namespace_directive (Using namespace directives) imports the type members of a namespace.

Using_static_directive (使用静态指令) 导入类型的嵌套类型和静态成员。A using_static_directive (Using static directives) imports the nested types and static members of a type.

Using_directive 的作用域超出其立即包含编译单元或命名空间正文的 namespace_member_declarationThe scope of a using_directive extends over the namespace_member_declaration s of its immediately containing compilation unit or namespace body. Using_directive 的作用域具体不包括其对等 using_directiveThe scope of a using_directive specifically does not include its peer using_directive s. 因此,对等 using_directive 不会相互影响,并且编写它们的顺序无关紧要。Thus, peer using_directive s do not affect each other, and the order in which they are written is insignificant.

使用 alias 指令Using alias directives

Using_alias_directive 引入了一个标识符,该标识符在直接封闭编译单元或命名空间体中充当命名空间或类型的别名。A using_alias_directive introduces an identifier that serves as an alias for a namespace or type within the immediately enclosing compilation unit or namespace body.

using_alias_directive
    : 'using' identifier '=' namespace_or_type_name ';'
    ;

在包含 using_alias_directive 的编译单元或命名空间正文中的成员声明中, using_alias_directive 引入的标识符可用于引用给定的命名空间或类型。Within member declarations in a compilation unit or namespace body that contains a using_alias_directive, the identifier introduced by the using_alias_directive can be used to reference the given namespace or type. 例如:For example:

namespace N1.N2
{
    class A {}
}

namespace N3
{
    using A = N1.N2.A;

    class B: A {}
}

以上,命名空间中的成员声明内 N3 A 是的别名 N1.N2.A ,因此类 N3.B 派生自类 N1.N2.AAbove, within member declarations in the N3 namespace, A is an alias for N1.N2.A, and thus class N3.B derives from class N1.N2.A. 为此,可以创建一个别名 R N1.N2 ,然后引用 R.AThe same effect can be obtained by creating an alias R for N1.N2 and then referencing R.A:

namespace N3
{
    using R = N1.N2;

    class B: R.A {}
}

Using_alias_directive标识符 在立即包含 using_alias_directive 的编译单元或命名空间的声明空间内必须是唯一的。The identifier of a using_alias_directive must be unique within the declaration space of the compilation unit or namespace that immediately contains the using_alias_directive. 例如:For example:

namespace N3
{
    class A {}
}

namespace N3
{
    using A = N1.N2.A;        // Error, A already exists
}

上面 N3 已包含成员 A ,因此 using_alias_directive 使用该标识符是编译时错误。Above, N3 already contains a member A, so it is a compile-time error for a using_alias_directive to use that identifier. 同样,同一编译单元或命名空间体中的两个或多个 using_alias_directive s 的编译时错误,用同一名称声明别名。Likewise, it is a compile-time error for two or more using_alias_directive s in the same compilation unit or namespace body to declare aliases by the same name.

Using_alias_directive 使别名在特定编译单元或命名空间体中可用,但不会将任何新成员分配给基础声明空间。A using_alias_directive makes an alias available within a particular compilation unit or namespace body, but it does not contribute any new members to the underlying declaration space. 换句话说, using_alias_directive 是不可传递的,而只会影响其出现在其中的编译单元或命名空间正文。In other words, a using_alias_directive is not transitive but rather affects only the compilation unit or namespace body in which it occurs. 示例中In the example

namespace N3
{
    using R = N1.N2;
}

namespace N3
{
    class B: R.A {}            // Error, R unknown
}

R 仅引入包含它的命名空间正文中的成员声明的 using_alias_directive 的范围,因此 R 在第二个命名空间声明中是未知的。the scope of the using_alias_directive that introduces R only extends to member declarations in the namespace body in which it is contained, so R is unknown in the second namespace declaration. 但是,将 using_alias_directive 放置在包含编译单元中会导致别名在两个命名空间声明中都可用:However, placing the using_alias_directive in the containing compilation unit causes the alias to become available within both namespace declarations:

using R = N1.N2;

namespace N3
{
    class B: R.A {}
}

namespace N3
{
    class C: R.A {}
}

与常规成员一样,由 using_alias_directive s 引入的名称将被嵌套作用域中名称类似的成员隐藏。Just like regular members, names introduced by using_alias_directive s are hidden by similarly named members in nested scopes. 示例中In the example

using R = N1.N2;

namespace N3
{
    class R {}

    class B: R.A {}        // Error, R has no member A
}

R.A在的声明中对的引用 B 会导致编译时错误,这 R 是因为引用了 N3.R ,而不是 N1.N2the reference to R.A in the declaration of B causes a compile-time error because R refers to N3.R, not N1.N2.

写入 using_alias_directive 的顺序并不重要,并且由 using_alias_directive 引用的 namespace_or_type_name 的解析不受 using_alias_directive 本身或直接包含编译单元或命名空间体中的其他 using_directive 的影响。The order in which using_alias_directive s are written has no significance, and resolution of the namespace_or_type_name referenced by a using_alias_directive is not affected by the using_alias_directive itself or by other using_directive s in the immediately containing compilation unit or namespace body. 换言之, using_alias_directivenamespace_or_type_name 将被解析,就好像直接包含编译单元或命名空间正文没有 using_directiveIn other words, the namespace_or_type_name of a using_alias_directive is resolved as if the immediately containing compilation unit or namespace body had no using_directive s. using_alias_directive 可能会受到直接包含编译单元或命名空间体中 extern_alias_directive s 的影响。A using_alias_directive may however be affected by extern_alias_directive s in the immediately containing compilation unit or namespace body. 示例中In the example

namespace N1.N2 {}

namespace N3
{
    extern alias E;

    using R1 = E.N;        // OK

    using R2 = N1;         // OK

    using R3 = N1.N2;      // OK

    using R4 = R2.N2;      // Error, R2 unknown
}

最后一个 using_alias_directive 会导致编译时错误,因为它不受第一个 using_alias_directive 的影响。the last using_alias_directive results in a compile-time error because it is not affected by the first using_alias_directive. 第一个 using_alias_directive 不会导致错误,因为 extern 别名的作用域 E 包含 using_alias_directiveThe first using_alias_directive does not result in an error since the scope of the extern alias E includes the using_alias_directive.

Using_alias_directive 可以为任何命名空间或类型创建别名,包括它所在的命名空间,以及嵌套在该命名空间中的任何命名空间或类型。A using_alias_directive can create an alias for any namespace or type, including the namespace within which it appears and any namespace or type nested within that namespace.

通过别名访问命名空间或类型会生成与通过其声明名称访问该命名空间或类型完全相同的结果。Accessing a namespace or type through an alias yields exactly the same result as accessing that namespace or type through its declared name. 例如,给定For example, given

namespace N1.N2
{
    class A {}
}

namespace N3
{
    using R1 = N1;
    using R2 = N1.N2;

    class B
    {
        N1.N2.A a;            // refers to N1.N2.A
        R1.N2.A b;            // refers to N1.N2.A
        R2.A c;               // refers to N1.N2.A
    }
}

名称 N1.N2.AR1.N2.AR2.A 都是等效的,并且都引用完全限定名称为的类 N1.N2.Athe names N1.N2.A, R1.N2.A, and R2.A are equivalent and all refer to the class whose fully qualified name is N1.N2.A.

使用别名可以命名封闭式构造类型,但不能在不提供类型实参的情况下命名未绑定的泛型类型声明。Using aliases can name a closed constructed type, but cannot name an unbound generic type declaration without supplying type arguments. 例如:For example:

namespace N1
{
    class A<T>
    {
        class B {}
    }
}

namespace N2
{
    using W = N1.A;          // Error, cannot name unbound generic type

    using X = N1.A.B;        // Error, cannot name unbound generic type

    using Y = N1.A<int>;     // Ok, can name closed constructed type

    using Z<T> = N1.A<T>;    // Error, using alias cannot have type parameters
}

使用命名空间指令Using namespace directives

Using_namespace_directive 将命名空间中包含的类型导入到紧靠后的编译单元或命名空间体中,从而在无限制的情况下使用每种类型的标识符。A using_namespace_directive imports the types contained in a namespace into the immediately enclosing compilation unit or namespace body, enabling the identifier of each type to be used without qualification.

using_namespace_directive
    : 'using' namespace_name ';'
    ;

在包含 using_namespace_directive 的编译单元或命名空间正文中的成员声明中,可以直接引用给定命名空间中包含的类型。Within member declarations in a compilation unit or namespace body that contains a using_namespace_directive, the types contained in the given namespace can be referenced directly. 例如:For example:

namespace N1.N2
{
    class A {}
}

namespace N3
{
    using N1.N2;

    class B: A {}
}

以上,在命名空间中的成员声明内 N3 ,的类型成员 N1.N2 直接可用,因而类 N3.B 派生自类 N1.N2.AAbove, within member declarations in the N3 namespace, the type members of N1.N2 are directly available, and thus class N3.B derives from class N1.N2.A.

Using_namespace_directive 导入给定命名空间中包含的类型,但不会专门导入嵌套命名空间。A using_namespace_directive imports the types contained in the given namespace, but specifically does not import nested namespaces. 示例中In the example

namespace N1.N2
{
    class A {}
}

namespace N3
{
    using N1;

    class B: N2.A {}        // Error, N2 unknown
}

using_namespace_directive 导入中包含的类型 N1 ,但不导入嵌套在中的命名空间 N1the using_namespace_directive imports the types contained in N1, but not the namespaces nested in N1. 因此,在的声明中对的引用 N2.A B 会导致编译时错误,因为 N2 在范围中没有名为的成员。Thus, the reference to N2.A in the declaration of B results in a compile-time error because no members named N2 are in scope.

using_alias_directive 不同, using_namespace_directive 可能会导入其标识符已在封闭编译单元或命名空间主体中定义的类型。Unlike a using_alias_directive, a using_namespace_directive may import types whose identifiers are already defined within the enclosing compilation unit or namespace body. 实际上,由 using_namespace_directive 导入的名称将被封闭编译单元或命名空间正文中名称类似的成员隐藏。In effect, names imported by a using_namespace_directive are hidden by similarly named members in the enclosing compilation unit or namespace body. 例如:For example:

namespace N1.N2
{
    class A {}

    class B {}
}

namespace N3
{
    using N1.N2;

    class A {}
}

此处,命名空间中的成员声明内 N3 A 引用 N3.A 而不是 N1.N2.AHere, within member declarations in the N3 namespace, A refers to N3.A rather than N1.N2.A.

如果在同一编译单元或命名空间正文中 using_namespace_directive s 或 using_static_directive s 导入多个命名空间或类型,则对该 type_name 名称的引用将被视为不明确。When more than one namespace or type imported by using_namespace_directive s or using_static_directive s in the same compilation unit or namespace body contain types by the same name, references to that name as a type_name are considered ambiguous. 示例中In the example

namespace N1
{
    class A {}
}

namespace N2
{
    class A {}
}

namespace N3
{
    using N1;

    using N2;

    class B: A {}                // Error, A is ambiguous
}

N1和都 N2 包含成员 A ,由于 N3 导入两者, A 在中引用 N3 是编译时错误。both N1 and N2 contain a member A, and because N3 imports both, referencing A in N3 is a compile-time error. 在这种情况下,可以通过对的引用 A 或引入特定的 using_alias_directive 来解决冲突 AIn this situation, the conflict can be resolved either through qualification of references to A, or by introducing a using_alias_directive that picks a particular A. 例如:For example:

namespace N3
{
    using N1;

    using N2;

    using A = N1.A;

    class B: A {}                // A means N1.A
}

而且,如果在同一编译单元或命名空间正文中 using_namespace_directive s 或 using_static_directive s 导入的多个命名空间或类型包含同名的类型或成员,则对该 simple_name 名称的引用将被视为不明确。Furthermore, when more than one namespace or type imported by using_namespace_directive s or using_static_directive s in the same compilation unit or namespace body contain types or members by the same name, references to that name as a simple_name are considered ambiguous. 示例中In the example

namespace N1
{
    class A {}
}

class C
{
    public static int A;
}

namespace N2
{
    using N1;
    using static C;

    class B
    {
        void M() 
        { 
            A a = new A();   // Ok, A is unambiguous as a type-name
            A.Equals(2);     // Error, A is ambiguous as a simple-name
        }
    }
}

N1 包含一个类型成员 AC 其中包含一个静态字段 A ,并且由于 N2 导入两者, A 作为 simple_name 引用不明确和编译时错误。N1 contains a type member A, and C contains a static field A, and because N2 imports both, referencing A as a simple_name is ambiguous and a compile-time error.

using_alias_directive 一样, using_namespace_directive 不会将任何新成员分配给编译单元或命名空间的基础声明空间,而只会影响其出现的编译单元或命名空间正文。Like a using_alias_directive, a using_namespace_directive does not contribute any new members to the underlying declaration space of the compilation unit or namespace, but rather affects only the compilation unit or namespace body in which it appears.

Using_namespace_directive 的引用 namespace_name 的解析方式与 using_alias_directive 引用的 namespace_or_type_name 相同。The namespace_name referenced by a using_namespace_directive is resolved in the same way as the namespace_or_type_name referenced by a using_alias_directive. 因此,同一编译单元或命名空间正文中的 using_namespace_directive 不会相互影响,并且可以按任意顺序写入。Thus, using_namespace_directive s in the same compilation unit or namespace body do not affect each other and can be written in any order.

使用静态指令Using static directives

Using_static_directive 将直接包含在类型声明中的嵌套类型和静态成员导入到立即封闭的编译单元或命名空间体中,从而在无限制的情况下使用每个成员和类型的标识符。A using_static_directive imports the nested types and static members contained directly in a type declaration into the immediately enclosing compilation unit or namespace body, enabling the identifier of each member and type to be used without qualification.

using_static_directive
    : 'using' 'static' type_name ';'
    ;

在包含 using_static_directive 的编译单元或命名空间正文中的成员声明中,可以直接引用可访问的嵌套类型和静态成员 (除在给定类型的声明中直接包含的扩展方法) 。Within member declarations in a compilation unit or namespace body that contains a using_static_directive, the accessible nested types and static members (except extension methods) contained directly in the declaration of the given type can be referenced directly. 例如:For example:

namespace N1
{
    class A 
    {
        public class B{}
        public static B M(){ return new B(); }
    }
}

namespace N2
{
    using static N1.A;
    class C
    {
        void N() { B b = M(); }
    }
}

以上,在命名空间中的成员声明内 N2 ,可以直接使用静态成员和嵌套类型 N1.A ,因此,该方法 N 能够同时引用的 BM 成员 N1.AAbove, within member declarations in the N2 namespace, the static members and nested types of N1.A are directly available, and thus the method N is able to reference both the B and M members of N1.A.

Using_static_directive 专门不将扩展方法直接导入为静态方法,但它们可用于扩展方法调用 (扩展方法调用) 。A using_static_directive specifically does not import extension methods directly as static methods, but makes them available for extension method invocation (Extension method invocations). 示例中In the example

namespace N1 
{
    static class A 
    {
        public static void M(this string s){}
    }
}

namespace N2
{
    using static N1.A;

    class B
    {
        void N() 
        {
            M("A");      // Error, M unknown
            "B".M();     // Ok, M known as extension method
            N1.A.M("C"); // Ok, fully qualified
        }
    }
}

using_static_directive 导入中包含的扩展方法 M N1.A ,但仅作为扩展方法。the using_static_directive imports the extension method M contained in N1.A, but only as an extension method. 因此,在主体中对的第一次引用 M B.N 会导致编译时错误,因为名为的成员不 M 在作用域内。Thus, the first reference to M in the body of B.N results in a compile-time error because no members named M are in scope.

Using_static_directive 只导入直接在给定类型中声明的成员和类型,而不导入在基类中声明的成员和类型。A using_static_directive only imports members and types declared directly in the given type, not members and types declared in base classes.

TODO:示例TODO: Example

使用命名空间指令讨论了多个 using_namespace_directivesusing_static_directives 之间的歧义。Ambiguities between multiple using_namespace_directives and using_static_directives are discussed in Using namespace directives.

命名空间成员Namespace members

Namespace_member_declaration Namespace_declaration (命名空间声明) 或 type_declaration ( 类型声明) 。A namespace_member_declaration is either a namespace_declaration (Namespace declarations) or a type_declaration (Type declarations).

namespace_member_declaration
    : namespace_declaration
    | type_declaration
    ;

编译单元或命名空间体可以包含 namespace_member_declaration,此类声明为包含编译单元或命名空间体的基础声明空间提供新成员。A compilation unit or a namespace body can contain namespace_member_declaration s, and such declarations contribute new members to the underlying declaration space of the containing compilation unit or namespace body.

类型声明Type declarations

Type_declarationclass_declaration (类声明) 、 struct_declaration ( 结构声明) 、interface_declaration ( 接口声明) 、 enum_declaration ( 枚举声明) 或 delegate_declaration ( 委托声明) 。A type_declaration is a class_declaration (Class declarations), a struct_declaration (Struct declarations), an interface_declaration (Interface declarations), an enum_declaration (Enum declarations), or a delegate_declaration (Delegate declarations).

type_declaration
    : class_declaration
    | struct_declaration
    | interface_declaration
    | enum_declaration
    | delegate_declaration
    ;

Type_declaration 可以作为编译单元中的顶级声明或命名空间、类或结构中的成员声明出现。A type_declaration can occur as a top-level declaration in a compilation unit or as a member declaration within a namespace, class, or struct.

如果类型声明类型 T 作为编译单元中的顶级声明出现,则新声明类型的完全限定名就是 TWhen a type declaration for a type T occurs as a top-level declaration in a compilation unit, the fully qualified name of the newly declared type is simply T. 当类型的类型声明 T 出现在命名空间、类或结构中时,新声明类型的完全限定名称为 N.T ,其中 N 是包含命名空间、类或结构的完全限定名称。When a type declaration for a type T occurs within a namespace, class, or struct, the fully qualified name of the newly declared type is N.T, where N is the fully qualified name of the containing namespace, class, or struct.

在类或结构中声明的类型称为嵌套类型 (嵌套类型) 。A type declared within a class or struct is called a nested type (Nested types).

类型声明的允许访问修饰符和默认访问权限取决于声明发生的上下文 (声明的可访问性) :The permitted access modifiers and the default access for a type declaration depend on the context in which the declaration takes place (Declared accessibility):

  • 在编译单元或命名空间中声明的类型可以具有 publicinternal 访问。Types declared in compilation units or namespaces can have public or internal access. 默认值为 " internal 访问"。The default is internal access.
  • 类中声明的类型可以具有 publicprotected internalprotectedinternalprivate 访问。Types declared in classes can have public, protected internal, protected, internal, or private access. 默认值为 " private 访问"。The default is private access.
  • 结构中声明的类型可以具有 publicinternalprivate 访问权限。Types declared in structs can have public, internal, or private access. 默认值为 " private 访问"。The default is private access.

命名空间别名限定符Namespace alias qualifiers

命名空间别名限定符 可以 :: 保证类型名称查找不受新类型和成员引入的影响。The namespace alias qualifier :: makes it possible to guarantee that type name lookups are unaffected by the introduction of new types and members. 命名空间别名限定符始终出现在两个标识符(称为左侧和右侧标识符)之间。The namespace alias qualifier always appears between two identifiers referred to as the left-hand and right-hand identifiers. 与常规 . 限定符不同,限定符的左侧标识符 :: 仅作为 extern 或 using 别名进行查找。Unlike the regular . qualifier, the left-hand identifier of the :: qualifier is looked up only as an extern or using alias.

Qualified_alias_member 定义如下:A qualified_alias_member is defined as follows:

qualified_alias_member
    : identifier '::' identifier type_argument_list?
    ;

Qualified_alias_member 可以用作 Namespace_or_type_name (命名空间和类型名称) 或作为 member_access (成员访问) 中的左操作数。A qualified_alias_member can be used as a namespace_or_type_name (Namespace and type names) or as the left operand in a member_access (Member access).

Qualified_alias_member 具有以下两种形式之一:A qualified_alias_member has one of two forms:

  • N::I<A1, ..., Ak>,其中 NI 表示标识符, <A1, ..., Ak> 是类型参数列表。N::I<A1, ..., Ak>, where N and I represent identifiers, and <A1, ..., Ak> is a type argument list. (K 始终是至少一个。 ) (K is always at least one.)
  • N::I,其中 NI 表示标识符。N::I, where N and I represent identifiers. 在这种情况下 (被 K 视为零。 ) (In this case, K is considered to be zero.)

使用此表示法,确定 qualified_alias_member 的含义,如下所示:Using this notation, the meaning of a qualified_alias_member is determined as follows:

  • 如果 N 是标识符 global ,则搜索全局命名空间以获取 IIf N is the identifier global, then the global namespace is searched for I:

    • 如果全局命名空间包含名为的命名空间  IK 为零,则 qualified_alias_member 引用该命名空间。If the global namespace contains a namespace named I and K is zero, then the qualified_alias_member refers to that namespace.
    • 否则,如果全局命名空间包含名为的非泛型类型  I 并且 K 为零,则 qualified_alias_member 引用该类型。Otherwise, if the global namespace contains a non-generic type named I and K is zero, then the qualified_alias_member refers to that type.
    • 否则,如果全局命名空间包含  I 具有类型参数的名为的类型 K   ,则 qualified_alias_member 引用使用给定类型参数构造的类型。Otherwise, if the global namespace contains a type named I that has K type parameters, then the qualified_alias_member refers to that type constructed with the given type arguments.
    • 否则, qualified_alias_member 是未定义的,并且发生编译时错误。Otherwise, the qualified_alias_member is undefined and a compile-time error occurs.
  • 否则,从命名空间声明开始 (命名空间声明) 立即包含 qualified_alias_member (如果有) ,则继续每个封闭命名空间声明 (如果有) ,并以包含 qualified_alias_member 的编译单元结束,则将计算以下步骤,直到找到实体:Otherwise, starting with the namespace declaration (Namespace declarations) immediately containing the qualified_alias_member (if any), continuing with each enclosing namespace declaration (if any), and ending with the compilation unit containing the qualified_alias_member, the following steps are evaluated until an entity is located:

    • 如果命名空间声明或编译单元包含 N 与某一类型关联的 using_alias_directive,则 qualified_alias_member 未定义并发生编译时错误。If the namespace declaration or compilation unit contains a using_alias_directive that associates N with a type, then the qualified_alias_member is undefined and a compile-time error occurs.
    • 否则,如果命名空间声明或编译单元包含与某个命名空间相关联的 extern_alias_directiveusing_alias_directive N ,则:Otherwise, if the namespace declaration or compilation unit contains an extern_alias_directive or using_alias_directive that associates N with a namespace, then:
      • 如果与关联的命名空间 N 包含名为的命名空间  IK 为零,则 qualified_alias_member 引用该命名空间。If the namespace associated with N contains a namespace named I and K is zero, then the qualified_alias_member refers to that namespace.
      • 否则,如果与关联的命名空间 N 包含名为的非泛型类型  I 并且 K 为零,则 qualified_alias_member 引用该类型。Otherwise, if the namespace associated with N contains a non-generic type named I and K is zero, then the qualified_alias_member refers to that type.
      • 否则,如果与关联的命名空间 N 包含  I 具有类型参数的名为的类型 K   ,则 qualified_alias_member 引用使用给定类型参数构造的类型。Otherwise, if the namespace associated with N contains a type named I that has K type parameters, then the qualified_alias_member refers to that type constructed with the given type arguments.
      • 否则, qualified_alias_member 是未定义的,并且发生编译时错误。Otherwise, the qualified_alias_member is undefined and a compile-time error occurs.
  • 否则, qualified_alias_member 是未定义的,并且发生编译时错误。Otherwise, the qualified_alias_member is undefined and a compile-time error occurs.

请注意,将命名空间别名限定符用于引用类型的别名会导致编译时错误。Note that using the namespace alias qualifier with an alias that references a type causes a compile-time error. 另请注意,如果标识符  Nglobal ,则将在全局命名空间中执行查找,即使存在使用 global 与类型或命名空间相关联的别名。Also note that if the identifier N is global, then lookup is performed in the global namespace, even if there is a using alias associating global with a type or namespace.

别名的唯一性Uniqueness of aliases

每个编译单元和命名空间正文都具有单独的用于 extern 别名和使用别名的声明空间。Each compilation unit and namespace body has a separate declaration space for extern aliases and using aliases. 因此,虽然 extern 别名的名称或 using 别名在外部别名集中必须是唯一的,并且使用在立即包含编译单元或命名空间体中声明的别名,但允许别名与类型或命名空间同名,只要它仅用于 :: 限定符。Thus, while the name of an extern alias or using alias must be unique within the set of extern aliases and using aliases declared in the immediately containing compilation unit or namespace body, an alias is permitted to have the same name as a type or namespace as long as it is used only with the :: qualifier.

示例中In the example

namespace N
{
    public class A {}

    public class B {}
}

namespace N
{
    using A = System.IO;

    class X
    {
        A.Stream s1;            // Error, A is ambiguous

        A::Stream s2;           // Ok
    }
}

名称在 A 第二个命名空间正文中有两个可能的含义 A ,因为该类和 using 别名 A 都在范围内。the name A has two possible meanings in the second namespace body because both the class A and the using alias A are in scope. 出于此原因, A 限定名称中的使用 A.Stream 不明确,导致发生编译时错误。For this reason, use of A in the qualified name A.Stream is ambiguous and causes a compile-time error to occur. 但是,使用 A with :: 限定符不是错误,因为 A 仅查找作为命名空间别名。However, use of A with the :: qualifier is not an error because A is looked up only as a namespace alias.