文件范围的命名空间

注意

本文是特性规范。 该规范充当该功能的设计文档。 它包括建议的规范更改,以及功能设计和开发过程中所需的信息。 这些文章将发布,直到建议的规范更改最终确定并合并到当前的 ECMA 规范中。

功能规范与已完成的实现之间可能存在一些差异。 这些差异记录在相关的语言设计会议 (LDM) 说明中。

可以在 规范一文中详细了解将功能规范采用 C# 语言标准的过程。

支持者问题:https://github.com/dotnet/csharplang/issues/137

总结

对于仅包含一个命名空间的文件的典型情况,文件范围命名空间使用更简洁的格式。 文件的命名空间格式为 namespace X.Y.Z;(请注意分号以及大括号的缺失)。 这允许如下所示的文件:

namespace X.Y.Z;

using System;

class X
{
}

语义是,使用 namespace X.Y.Z; 形式相当于写作 namespace X.Y.Z { ... },其中文件范围命名空间之后的文件剩余部分位于标准命名空间声明的 ... 部分。

动机

C# 生态系统的分析显示,大约 99.7 个% 文件都是以下任一形式之一:

namespace X.Y.Z
{
    // usings

    // types
}

// usings

namespace X.Y.Z
{
    // types
}

但是,这两种形式都强制用户缩进大部分代码,并为实际上非常基本的概念添加相当多的繁琐手续。 这会影响清晰度、使用水平空间和垂直空间,并且通常让习惯使用 C# 和来自其他语言(这里通常没有太多繁琐手续)的用户感到不满意。

因此,该功能的主要目标是通过减少不必要的模板代码,满足生态系统绝大部分的需求。

详细设计

此建议采用与规范中的现有编译单元 (§14.2) 部分不同的形式。

差异

compilation_unit 定义了源文件的整体结构。 编译单元由零个或多个 using_directive 组成,后面依次跟着零个或多个 global_attributes、零个或多个 namespace_member_declaration

compilation_unit 定义源代码文件的整体结构。 编译单元由零个或多个 using_directive 组成,后面依次跟着零个或多个 global_attributes 和一个 compilation_unit_bodycompilation_unit_body 可以是 file_scoped_namespace_declaration 或零个或多个语句namespace_member_declaration

compilation_unit
~~    : extern_alias_directive* using_directive* global_attributes? namespace_member_declaration*~~
    : extern_alias_directive* using_directive* global_attributes? compilation_unit_body
    ;

compilation_unit_body
    : statement* namespace_member_declaration*
    | file_scoped_namespace_declaration
    ;

...未改变...

file_scoped_namespace_declaration 将贡献语义上等效于 namespace_declaration 的对应成员。 有关详细信息,请参阅(命名空间声明)。

命名空间声明

namespace_declaration 由关键字 namespace 组成,后跟命名空间名称和主体,然后跟分号(可选)。 file_scoped_namespace_declaration 由关键字 namespace 组成,后跟命名空间名称、分号和可选的 extern_alias_directiveusing_directivetype_declaration 列表。

namespace_declaration
    : 'namespace' qualified_identifier namespace_body ';'?
    ;
    
file_scoped_namespace_declaration
    : 'namespace' qualified_identifier ';' extern_alias_directive* using_directive* type_declaration*
    ;

... unchanged ...

......没有变化......

上面的两个命名空间声明共同构成同一个声明空间,在本例中,定义了两个类,它们的完全限定名称是 N1.N2.AN1.N2.B。 由于这两个声明对同一声明空间的贡献,因此如果每个声明都包含同名成员的声明,则这将是一个错误。

file_scoped_namespace_declaration 允许在没有 { ... } 块的情况下编写命名空间声明。 例如:

extern alias A;
namespace Name;
using B;
class C
{
}

在语义上等效于

extern alias A;
namespace Name
{
    using B;
    class C
    {
    }
}

具体而言,file_scoped_namespace_declaration 被认为与 compilation_unit 中具有相同 qualified_identifier 的同一位置的 namespace_declaration 相同。 该 file_scoped_namespace_declarationextern_alias_directiveusing_directivetype_declaration 的行为就像它们在该 namespace_declarationnamespace_body 内以相同顺序声明一样。

源文件不能同时包含 file_scoped_namespace_declarationnamespace_declaration。 源文件不能包含多个 file_scoped_namespace_declarationcompilation_unit 不能同时包含 file_scoped_namespace_declaration 和任何顶级语句type_declaration 不能位于 file_scoped_namespace_declaration 之前。

外部别名

...不变……