Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions standard/basic-concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ A declaration defines a name in the ***declaration space*** to which the declara
There are several different types of declaration spaces, as described in the following.

- Within all compilation units of a program, *namespace_member_declaration*s with no enclosing *namespace_declaration* are members of a single combined declaration space called the ***global declaration space***.
- Within all compilation units of a program, *namespace_member_declaration*s within *namespace_declaration*s that have the same fully qualified namespace name are members of a single combined declaration space.
- Within all compilation units of a program, *compilation_unit_body*s that have the same fully qualified namespace name are members of a single combined declaration space.
- Each *compilation_unit* and *namespace_body* has an ***alias declaration space***. Each *extern_alias_directive* and *using_alias_directive* of the *compilation_unit* or *namespace_body* contributes a member to the alias declaration space ([§14.5.2](namespaces.md#1452-using-alias-directives)).
- Each non-partial class, struct, or interface declaration creates a new declaration space. Each partial class, struct, or interface declaration contributes to a declaration space shared by all matching parts in the same program ([§16.2.4](structs.md#1624-partial-modifier)). Names are introduced into this declaration space through *class_member_declaration*s, *struct_member_declaration*s, *interface_member_declaration*s, or *type_parameter*s. Except for overloaded instance constructor declarations and static constructor declarations, a class, struct, or interface cannot contain a member declaration with the same name as the class, struct, or interface. A class, struct, or interface permits the declaration of overloaded methods and indexers. Furthermore, a class or struct permits the declaration of overloaded instance constructors and operators. For example, a class, struct, or interface may contain multiple method declarations with the same name, provided these method declarations differ in their signature ([§7.6](basic-concepts.md#76-signatures-and-overloading)). Note that base classes do not contribute to the declaration space of a class, and base interfaces do not contribute to the declaration space of an interface. Thus, a derived class or interface is allowed to declare a member with the same name as an inherited member. Such a member is said to ***hide*** the inherited member.
- Each delegate declaration creates a new declaration space. Names are introduced into this declaration space through parameters (*fixed_parameter*s and *parameter_array*s) and *type_parameter*s.
Expand Down Expand Up @@ -772,9 +772,9 @@ The ***scope*** of a name is the region of program text within which it is possi
> *Note*: It may not be possible to access the hidden outer name from the inner scope because there is no way of qualifying it, such as with type parameters on nested type declarations. *end note*

- The scope of a namespace member declared by a *namespace_member_declaration* ([§14.6](namespaces.md#146-namespace-member-declarations)) with no enclosing *namespace_declaration* is the entire program text.
- The scope of a namespace member declared by a *namespace_member_declaration* within a *namespace_declaration* whose fully qualified name is `N`, is the *namespace_body* of every *namespace_declaration* whose fully qualified name is `N` or starts with `N`, followed by a period.
- The scope of a name defined by an *extern_alias_directive* ([§14.4](namespaces.md#144-extern-alias-directives)) extends over the *using_directive*s, *global_attributes* and *namespace_member_declaration*s of its immediately containing *compilation_unit* or *namespace_body*. An *extern_alias_directive* does not contribute any new members to the underlying declaration space. In other words, an *extern_alias_directive* is not transitive, but, rather, affects only the *compilation_unit* or *namespace_body* in which it occurs.
- The scope of a name defined or imported by a *using_directive* ([§14.5](namespaces.md#145-using-directives)) extends over the *global_attributes* and *namespace_member_declaration*s of the *compilation_unit* or *namespace_body* in which the *using_directive* occurs. A *using_directive* may make zero or more namespace or type names available within a particular *compilation_unit* or *namespace_body*, but does not contribute any new members to the underlying declaration space. In other words, a *using_directive* is not transitive but rather affects only the *compilation_unit* or *namespace_body* in which it occurs.
- The scope of a namespace member declared by a *compilation_unit_body* whose fully qualified name is `N`, is every *compilation_unit_body* whose fully qualified name is `N` or starts with `N`, followed by a period.
- The scope of a name defined by an *extern_alias_directive* ([§14.4](namespaces.md#144-extern-alias-directives)) extends over the *using_directive*s, *global_attributes*, and *compilation_unit_body* of its immediately containing *compilation_unit* or *namespace_body*. An *extern_alias_directive* does not contribute any new members to the underlying declaration space. In other words, an *extern_alias_directive* is not transitive, but, rather, affects only the *compilation_unit*, *namespace_body*, and *file_scoped_namespace_declaration* in which it occurs.
- The scope of a name defined or imported by a *using_directive* ([§14.5](namespaces.md#145-using-directives)) extends over the *global_attributes* and *compilation_unit_body* of the *compilation_unit* or *namespace_body* in which the *using_directive* occurs. A *using_directive* may make zero or more namespace or type names available within a particular *compilation_unit*, *namespace_body*, and *file_scoped_namespace_declaration* but does not contribute any new members to the underlying declaration space. In other words, a *using_directive* is not transitive but rather affects only the *compilation_unit*, *namespace_body*, and *file_scoped_namespace_declaration* in which it occurs.
Comment on lines +776 to +777
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect that eventually there will be a conflict generated by these bullet items. These edits are built on top of the edits for the V9 feature "Top-Level Statements" (see PR #1454). And just an hour ago, I tweaked that PR to include "statement_lists" in two places in these items. Ultimately, this PR will need to remove those bits of text as their inclusion is subsumed by this PR.

- The scope of a type parameter declared by a *type_parameter_list* on a *class_declaration* ([§15.2](classes.md#152-class-declarations)) is the *class_base*, *type_parameter_constraints_clause*s, and *class_body* of that *class_declaration*.
> *Note*: Unlike members of a class, this scope does not extend to derived classes. *end note*
- The scope of a type parameter declared by a *type_parameter_list* on a *struct_declaration* ([§16.2](structs.md#162-struct-declarations)) is the *struct_interfaces*, *type_parameter_constraints_clause*s, and *struct_body* of that *struct_declaration*.
Expand Down
69 changes: 59 additions & 10 deletions standard/namespaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,30 @@

## 14.2 Compilation units

A *compilation_unit* consists of zero or more *extern_alias_directive*s followed by zero or more *using_directive*s followed by zero or one *global_attributes* followed by zero or more *statement_list*s followed by zero or more *namespace_member_declaration*s. The *compilation_unit* defines the overall structure of the input.
A *compilation_unit* consists of zero or more *extern_alias_directive*s followed by zero or more *using_directive*s followed by zero or one *global_attributes* followed by a *compilation_unit_body*. A *compilation_unit_body* can either be zero or more *statement_list*s followed by zero or more *namespace_member_declaration*s, or a *file_scoped_namespace_declaration*. The *compilation_unit* defines the overall structure of the input.

```ANTLR
compilation_unit

Check warning on line 14 in standard/namespaces.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/namespaces.md#L14

MDC032::Line length 87 > maximum 81
: extern_alias_directive* using_directive* global_attributes?
statement_list* namespace_member_declaration*
: extern_alias_directive* using_directive* global_attributes? compilation_unit_body
;
compilation_unit_body
: statement_list* namespace_member_declaration*
| file_scoped_namespace_declaration
;
```

A C# program consists of one or more compilation units. 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.

The *extern_alias_directive*s of a compilation unit affect the *using_directive*s, *global_attributes* and *namespace_member_declaration*s of that compilation unit, but have no effect on other compilation units.
The *extern_alias_directive*s of a compilation unit affect the *using_directive*s, *global_attributes* and *compilation_unit_body* of that compilation unit, but have no effect on other compilation units.

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.
The *using_directive*s of a compilation unit affect the *global_attributes* and *compilation_unit_body* of that compilation unit, but have no effect on other compilation units.

The *global_attributes* ([§23.3](attributes.md#233-attribute-specification)) 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.

The *namespace_member_declaration*s of each compilation unit of a program contribute members to a single declaration space called the global namespace.
The *namespace_member_declaration*s or *file_scoped_namespace_declaration* of each compilation unit of a program contribute members to a single declaration space called the global namespace.

A *file_scoped_namespace_declaration* contributes members corresponding to the *namespace_declaration* to which it is semantically equivalent ([§14.3](namespaces.md#143-namespace-declarations)).

> *Example*:
>
Expand All @@ -43,13 +49,18 @@
## 14.3 Namespace declarations
A *namespace_declaration* consists of the keyword namespace, followed by a namespace name and body, optionally followed by a semicolon.
A *namespace_declaration* consists of the keyword namespace, followed by a namespace name and body, optionally followed by a semicolon. A *file_scoped_namespace_declaration* consists of the keyword `namespace`, followed by a namespace name, a semicolon, and an optional list of *extern_alias_directive*s, *using_directive*s and *type_declaration*s.
```ANTLR
namespace_declaration
: 'namespace' qualified_identifier namespace_body ';'?
;
file_scoped_namespace_declaration

Check warning on line 59 in standard/namespaces.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/namespaces.md#L59

MDC032::Line length 83 > maximum 81
: 'namespace' qualified_identifier ';' extern_alias_directive* using_directive*
type_declaration*
;
qualified_identifier
: identifier ('.' identifier)*
;
Expand All @@ -62,11 +73,15 @@
A *namespace_declaration* may occur as a top-level declaration in a *compilation_unit* or as a member declaration within another *namespace_declaration*. When a *namespace_declaration* occurs as a top-level declaration in a *compilation_unit*, the namespace becomes a member of the global namespace. 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 shall be unique within the containing namespace.

A *file_scoped_namespace_declaration* may only occur as a top-level declaration in a *compilation_unit*. As such, the declared namespace becomes a member of the global namespace.

Namespaces are implicitly `public` and the declaration of a namespace cannot include any access modifiers.

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. The optional *namespace_member_declaration*s contribute members to the declaration space of the namespace. Note that all *using_directive*s shall appear before any member declarations.

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.
Within a *file_scoped_namespace_declaration*, 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. The optional *type_declaration*s contribute members to the declaration space of the namespace. Note that all *using_directive*s shall appear before any type declarations.

The *qualified_identifier* of a *namespace_declaration* and *file_scoped_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.

> *Example*:
>
Expand Down Expand Up @@ -116,6 +131,40 @@
>
> *end example*
A *file_scoped_namespace_declaration* permits a namespace declaration to be written without an accompanying `{ … }` block.
> *Example*:
>
> <!-- Example: {template:"standalone-lib-without-using", name:"FileScopedNamespaces1"} -->
> ```csharp
> namespace Name;
> using System;
> class C
> {
> }
> ```
>
> is semantically equivalent to
>
> <!-- Example: {template:"standalone-lib-without-using", name:"FileScopedNamespaces2"} -->
> ```csharp
> namespace Name
> {
> using System;
> class C
> {
> }
> }
> ```
>
> *end example*
A *file_scoped_namespace_declaration* is treated the same as a *namespace_declaration* at the same location in the *compilation_unit* with the same *qualified_identifier*. The *extern_alias_directive*s, *using_directive*s and *type_declaration*s of that *file_scoped_namespace_declaration* act as if they were declared in the same order inside the *namespace_body* of that *namespace_declaration*.
> *Note*: As determined by the grammar, a compilation unit cannot contain both a *file_scoped_namespace_declaration* and a *namespace_declaration*. It cannot contain multiple *file_scoped_namespace_declaration*s. It cannot contain both a *file_scoped_namespace_declaration* and any top level *statement*s. *type_declaration*s cannot precede a *file_scoped_namespace_declaration*. *end note*
Different compilation units may contribute to the same namespace using either or both of the *namespace_member_declaration* or *file_scoped_namespace_declaration* syntax.
## 14.4 Extern alias directives
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.
Expand All @@ -126,7 +175,7 @@
;
```
The 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*.
The scope of an *extern_alias_directive* is described in [§7.7.1]( basic-concepts.md#771-general).
Copy link
Contributor Author

@RexJaeschke RexJaeschke Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, I invoked the spec-writing rule, "Don't say the same thing in two different places!"


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. It is a compile-time error for the *identifier* to be the word `global`.

Expand Down Expand Up @@ -175,7 +224,7 @@

A *using_static_directive* ([§14.5.4](namespaces.md#1454-using-static-directives)) imports the nested types and static members of a type.

The scope of a *using_directive* extends over the *namespace_member_declarations* of its immediately containing compilation unit or namespace body. The scope of a *using_directive* specifically does not include its peer *using_directive*s. Thus, peer *using_directive*s do not affect each other, and the order in which they are written is insignificant. In contrast, the scope of an *extern_alias_directive* includes the *using_directive*s defined in the same compilation unit or namespace body.
The scope of a *using_directive* is described in [§7.7.1]( basic-concepts.md#771-general).
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, I invoked the spec-writing rule, "Don't say the same thing in two different places!"


### 14.5.2 Using alias directives

Expand Down
Loading