Global using directive - C# feature specifications (original) (raw)

Note

This article is a feature specification. The specification serves as the design document for the feature. It includes proposed specification changes, along with information needed during the design and development of the feature. These articles are published until the proposed spec changes are finalized and incorporated in the current ECMA specification.

There may be some discrepancies between the feature specification and the completed implementation. Those differences are captured in the pertinent language design meeting (LDM) notes.

You can learn more about the process for adopting feature speclets into the C# language standard in the article on the specifications.

Champion issue: https://github.com/dotnet/csharplang/issues/3428

Syntax for a using directive is extended with an optional global keyword that can precede the using keyword:

compilation_unit
    : extern_alias_directive* global_using_directive* using_directive* global_attributes? namespace_member_declaration*
    ;

global_using_directive
    : global_using_alias_directive
    | global_using_namespace_directive
    | global_using_static_directive
    ;

global_using_alias_directive
    : 'global' 'using' identifier '=' namespace_or_type_name ';'
    ;

global_using_namespace_directive
    : 'global' 'using' namespace_name ';'
    ;
    
global_using_static_directive
    : 'global' 'using' 'static' type_name ';'
    ;

The effect of adding a global_using_directive to a program can be thought of as the effect of adding a similar using_directive that resolves to the same target namespace or type to every compilation unit of the program. However, the target of a global_using_directive is resolved in context of the compilation unit that contains it.

§7.7 Scopes

These are the relevant bullet points with proposed additions (which are in bold):

§7.8 Namespace and type names

Changes are made to the algorithm determining the meaning of a namespace_or_type_name as follows.

This is the relevant bullet point with proposed additions (which are in bold):

Simple names §12.8.4

Changes are made to the simple_name evaluation rules as follows.

This is the relevant bullet point with proposed additions (which are in bold):

Extension method invocations §12.8.10.3

Changes are made to the algorithm to find the best type_name C as follows. This is the relevant bullet point with proposed additions (which are in bold):

Compilation units §14.2

A compilation_unit defines the overall structure of a source file. A compilation unit consists of zero or more _global_using_directive_s followed by 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* global_using_directive* using_directive* global_attributes? namespace_member_declaration*
    ;

A C# program consists of one or more compilation units, each contained in a separate source file. 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 _global_using_directive_s of a compilation unit affect the global_attributes and _namespace_member_declaration_s of all compilation units in the program.

Extern aliases §14.4

The scope of an extern_alias_directive extends over the _global_using_directive_s, _using_directive_s, global_attributes and _namespace_member_declaration_s of its immediately containing compilation unit or namespace body.

Using alias directives §14.5.2

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, and, if the using_alias_directive is immediately contained in a compilation unit, is not affected by the _global_using_directive_s in the program. In 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 and, if the using_alias_directive is immediately contained in a compilation unit, the program had no _global_using_directive_s. A using_alias_directive may however be affected by _extern_alias_directive_s in the immediately containing compilation unit or namespace body.

Global Using alias directives

A global_using_alias_directive introduces an identifier that serves as an alias for a namespace or type within the program.

global_using_alias_directive
    : 'global' 'using' identifier '=' namespace_or_type_name ';'
    ;

Within member declarations in any compilation unit of a program that contains a global_using_alias_directive, the identifier introduced by the global_using_alias_directive can be used to reference the given namespace or type.

The identifier of a global_using_alias_directive must be unique within the declaration space of any compilation unit of a program that contains the global_using_alias_directive.

Just like regular members, names introduced by _global_using_alias_directive_s are hidden by similarly named members in nested scopes.

The order in which _global_using_alias_directive_s are written has no significance, and resolution of the namespace_or_type_name referenced by a global_using_alias_directive is not affected by the global_using_alias_directive itself or by other _global_using_directive_s or _using_directive_s in the program. In other words, the namespace_or_type_name of a global_using_alias_directive is resolved as if the immediately containing compilation unit had no _using_directive_s and the entire containing program had no _global_using_directive_s. A global_using_alias_directive may however be affected by _extern_alias_directive_s in the immediately containing compilation unit.

A global_using_alias_directive can create an alias for any namespace or type.

Accessing a namespace or type through an alias yields exactly the same result as accessing that namespace or type through its declared name.

Using aliases can name a closed constructed type, but cannot name an unbound generic type declaration without supplying type arguments.

Global Using namespace directives

A global_using_namespace_directive imports the types contained in a namespace into the program, enabling the identifier of each type to be used without qualification.

global_using_namespace_directive
    : 'global' 'using' namespace_name ';'
    ;

Within member declarations in a program that contains a global_using_namespace_directive, the types contained in the given namespace can be referenced directly.

A global_using_namespace_directive imports the types contained in the given namespace, but specifically does not import nested namespaces.

Unlike a global_using_alias_directive, a global_using_namespace_directive may import types whose identifiers are already defined within a compilation unit of the program. In effect, in a given compilation unit, names imported by any global_using_namespace_directive in the program are hidden by similarly named members in the compilation unit.

When more than one namespace or type imported by _global_using_namespace_directive_s or _global_using_static_directive_s in the same program contain types by the same name, references to that name as a type_name are considered ambiguous.

Furthermore, when more than one namespace or type imported by _global_using_namespace_directive_s or _global_using_static_directive_s in the same program contain types or members by the same name, references to that name as a simple_name are considered ambiguous.

The namespace_name referenced by a global_using_namespace_directive is resolved in the same way as the namespace_or_type_name referenced by a global_using_alias_directive. Thus, _global_using_namespace_directive_s in the same program do not affect each other and can be written in any order.

Global Using static directives

A global_using_static_directive imports the nested types and static members contained directly in a type declaration into the containing program, enabling the identifier of each member and type to be used without qualification.

global_using_static_directive
    : 'global' 'using' 'static' type_name ';'
    ;

Within member declarations in a program that contains a global_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.

A global_using_static_directive specifically does not import extension methods directly as static methods, but makes them available for extension method invocation.

A global_using_static_directive only imports members and types declared directly in the given type, not members and types declared in base classes.

Ambiguities between multiple _global_using_namespace_directive_s and global_using_static_directives are discussed in the section for _global_using_namespace_directive_s (above).

Qualified alias member §14.8

Changes are made to the algorithm determining the meaning of a qualified_alias_member as follows.

This is the relevant bullet point with proposed additions (which are in bold):