Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
14.1 General
Программы C# упорядочены с помощью пространств имен. Пространства имен используются как в качестве внутренней системы организации для программы, так и как внешняя система организации — способ представления элементов программы, предоставляемых другим программам.
Using directives (§14.5) are provided to facilitate the use of namespaces.
Единицы компиляции 14.2
A compilation_unit consists of zero or more extern_alias_directives followed by zero or more using_directives followed by zero or one global_attributes followed by zero or more namespace_member_declarations. The compilation_unit defines the overall structure of the input.
compilation_unit
: extern_alias_directive* using_directive* global_attributes?
namespace_member_declaration*
;
Программа C# состоит из одного или нескольких единиц компиляции. При компиляции программы C# все единицы компиляции обрабатываются вместе. Таким образом, единицы компиляции могут зависеть друг от друга, возможно, в циклической форме.
The extern_alias_directives of a compilation unit affect the using_directives, global_attributes and namespace_member_declarations of that compilation unit, but have no effect on other compilation units.
The using_directives of a compilation unit affect the global_attributes and namespace_member_declarations of that compilation unit, but have no effect on other compilation units.
The global_attributes (§22.3) of a compilation unit permit the specification of attributes for the target assembly and module. Сборки и модули служат физическими контейнерами для типов. Сборка может состоять из нескольких физически отдельных модулей.
The namespace_member_declarations of each compilation unit of a program contribute members to a single declaration space called the global namespace.
Example:
// File A.cs: class A {} // File B.cs: class B {}
Два единицы компиляции способствуют одному глобальному пространству имен, в этом случае объявляя два класса с полными именами
A
иB
. Так как два единици компиляции способствуют одному и тому же пространству объявлений, это было бы ошибкой, если каждая из них содержала объявление члена с одинаковым именем.end example
Объявления пространства имен 14.3
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* '}'
;
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. В любом случае имя пространства имен должно быть уникальным в пределах содержащего пространства имен.
Пространства имен неявно public
и объявление пространства имен не может включать модификаторы доступа.
Within a namespace_body, the optional using_directives import the names of other namespaces, types and members, allowing them to be referenced directly instead of through qualified names. The optional namespace_member_declarations contribute members to the declaration space of the namespace. Note that all using_directives 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. Последняя форма позволяет программе определять вложенное пространство имен без лексического вложения нескольких объявлений пространства имен.
Example:
namespace N1.N2 { class A {} class B {} }
семантически эквивалентен
namespace N1 { namespace N2 { class A {} class B {} } }
end example
Namespaces are open-ended, and two namespace declarations with the same fully qualified name (§7.8.3) contribute to the same declaration space (§7.3).
Example: In the following code
namespace N1.N2 { class A {} } namespace N1.N2 { class B {} }
Два объявления пространства имен, приведенные выше, способствуют одному и тому же пространству объявлений, в этом случае объявляя два класса с полными именами
N1.N2.A
иN1.N2.B
. Так как два объявления способствуют одному и тому же пространству объявлений, это было бы ошибкой, если каждая из них содержала объявление члена с одинаковым именем.end example
Директивы псевдонима Extern 14.4
An extern_alias_directive introduces an identifier that serves as an alias for a namespace. Спецификация псевдонима пространства имен является внешней к исходному коду программы и применяется также к вложенным пространствам имен псевдонима пространства имен.
extern_alias_directive
: 'extern' 'alias' identifier ';'
;
The scope of an extern_alias_directive extends over the using_directives, global_attributes and namespace_member_declarations of its immediately containing compilation_unit or namespace_body.
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
.
The alias introduced by an extern_alias_directive is very similar to the alias introduced by a using_alias_directive. See §14.5.2 for more detailed discussion of extern_alias_directives and using_alias_directives.
alias
is a contextual keyword (§6.4.4) and only has special meaning when it immediately follows the extern
keyword in an extern_alias_directive.
Ошибка возникает, если программа объявляет экстерн-псевдоним, для которого отсутствует внешнее определение.
Example: The following program declares and uses two extern aliases,
X
andY
, 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; }
Программа объявляет существование экстерн-псевдонимов
X
иY
, однако фактические определения псевдонимов являются внешними для программы. Теперь классы с одинаковыми именамиN.B
можно ссылаться какX.N.B
и (илиY.N.B
) с помощью квалификатораX::N.B
пространства имен иY::N.B
. end example
Директивы using 14.5
14.5.1 General
Using directives facilitate the use of namespaces and types defined in other namespaces. Using directives impact the name resolution process of namespace_or_type_names (§7.8) and simple_names (§12.8.4), 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
;
A using_alias_directive (§14.5.2) introduces an alias for a namespace or type.
A using_namespace_directive (§14.5.3) imports the type members of a namespace.
A using_static_directive (§14.5.4) 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_directives. Thus, peer using_directives 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_directives defined in the same compilation unit or namespace body.
14.5.2 Использование директив псевдонима
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 ';'
;
Within global attributes and 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.
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.A
. Тот же эффект можно получить путем создания псевдонимаR
дляN1.N2
и последующегоR.A
ссылки:namespace N3 { using R = N1.N2; class B : R.A {} }
end example
Within using directives, global attributes and member declarations in 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 associated namespace.
Example: For example:
namespace N1 { extern alias N2; class B : N2::A {} }
Выше в объявлениях членов в
N1
пространстве имен используется псевдоним для определенного пространства имен,N2
определение которого является внешним исходным кодом программы. КлассN1.B
является производным от классаN2.A
. Тот же эффект можно получить путем создания псевдонимаA
дляN2.A
и последующегоA
ссылки:namespace N1 { extern alias N2; using A = N2::A; class B : A {} }
end example
An extern_alias_directive or 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. Другими словами, директива псевдонима не является транзитивной, но, скорее, влияет только на блок компиляции или тело пространства имен, в котором она происходит.
Example: In the following code
namespace N3 { extern alias R1; using R2 = N1.N2; } namespace N3 { class B : R1::A, R2.I {} // Error, R1 and R2 unknown }
области директив псевдонима, которые вводят
R1
иR2
расширяют только объявления членов в теле пространства имен, в котором они содержатся, поэтомуR1
иR2
неизвестны во втором объявлении пространства имен. Однако размещение директив псевдонима в блоке компиляции приводит к тому, что псевдоним становится доступным в обоих объявлениях пространства имен:extern alias R1; using R2 = N1.N2; namespace N3 { class B : R1::A, R2.I {} } namespace N3 { class C : R1::A, R2.I {} }
end example
Each extern_alias_directive or using_alias_directive in a compilation_unit or namespace_body contributes a name to the alias declaration space (§7.3) of the immediately enclosing compilation_unit or namespace_body. The identifier of the alias directive shall be unique within the corresponding alias declaration space. Идентификатор псевдонима не должен быть уникальным в пределах глобального пространства объявлений или пространства объявления соответствующего пространства имен.
Example:
extern alias X; extern alias Y; using X = N1.N2; // Error: alias X already exists class Y {} // Ok
Именованный псевдоним
X
используется, так как в той же единице компиляции уже есть псевдонимX
. Именованный классY
не конфликтует с псевдонимом extern,Y
так как эти имена добавляются в отдельные пространства объявлений. Первый добавляется в глобальное пространство объявления, а последний добавляется в пространство объявлений псевдонима для этой единицы компиляции.Если имя псевдонима совпадает с именем члена пространства имен, использование любого из этих имен должно быть соответствующим образом квалифицировано:
namespace N1.N2 { class B {} } namespace N3 { class A {} class B : A {} } namespace N3 { using A = N1.N2; using B = N1.N2.B; class W : B {} // Error: B is ambiguous class X : A.B {} // Error: A is ambiguous class Y : A::B {} // Ok: uses N1.N2.B class Z : N3.B {} // Ok: uses N3.B }
Во втором тексте
N3
пространства имен для неквалифицированного использованияB
результатов ошибки, так какN3
содержит элемент с именемB
и тело пространства имен, которое также объявляет псевдоним с именемB
; аналогично.A
N3.B
Класс можно ссылаться какN3.B
илиglobal::N3.B
. The aliasA
can be used in a qualified-alias-member (§14.8), such asA::B
. ПсевдонимB
по сути бесполезен. It cannot be used in a qualified_alias_member since only namespace aliases can be used in a qualified_alias_member andB
aliases a type.end example
Just like regular members, names introduced by alias_directives are hidden by similarly named members in nested scopes.
Example: In the following code
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.N2
end example
The order in which extern_alias_directives are written has no significance. Likewise, the order in which using_alias_directives are written has no significance, but all using_alias_directives shall come after all extern_alias_directives in the same compilation unit or namespace body. 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_directives in the immediately containing compilation unit or namespace body, but may be affected by extern_alias_directives in the immediately containing compilation unit or namespace body. 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_directives but has the correct set of extern_alias_directives.
Example: In the following code
namespace N1.N2 {} namespace N3 { extern alias X; using R1 = X::N; // OK using R2 = N1; // OK using R3 = N1.N2; // OK using R4 = R2.N2; // Error, R2 unknown }
the last using_alias_directive results in a compile-time error because it is not affected by the previous using_alias_directive. The first using_alias_directive does not result in an error since the scope of the extern alias X includes the using_alias_directive.
end example
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.
Доступ к пространству имен или типу с помощью псевдонима дает точно тот же результат, что и доступ к пространству имен или типу через объявленное имя.
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.A
,R1.N2.A
и эквивалентны иR2.A
все ссылаются на объявление класса, полное имя которого .N1.N2.A
end example
Although each part of a partial type (§15.2.7) is declared within the same namespace, the parts are typically written within different namespace declarations. Thus, different extern_alias_directives and using_directives can be present for each part. When interpreting simple names (§12.8.4) within one part, only the extern_alias_directives and using_directives of the namespace bodies and compilation unit enclosing that part are considered. Это может привести к тому, что один и тот же идентификатор имеет разные значения в разных частях.
Example:
namespace N { using List = System.Collections.ArrayList; partial class A { List x; // x has type System.Collections.ArrayList } } namespace N { using List = Widgets.LinkedList; partial class A { List y; // y has type Widgets.LinkedList } }
end example
Используя псевдонимы, можно назвать закрытый созданный тип, но не удается назвать объявление универсального типа без указания аргументов типа.
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 }
end example
14.5.3 С помощью директив пространства имен
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 ';'
;
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.
Example:
namespace N1.N2 { class A {} } namespace N3 { using N1.N2; class B : A {} }
Выше в объявлениях членов в
N3
пространстве имен членыN1.N2
члены являются доступными напрямую и таким образом классN3.B
является производным от классаN1.N2.A
.end example
A using_namespace_directive imports the types contained in the given namespace, but specifically does not import nested namespaces.
Example: In the following code
namespace N1.N2 { class A {} } namespace N3 { using N1; class B : N2.A {} // Error, N2 unknown }
the using_namespace_directive imports the types contained in
N1
, but not the namespaces nested inN1
. Таким образом, ссылка наN2.A
объявление приводит к ошибке во время компиляцииB
, так как именованныеN2
элементы не находятся в области.end example
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. In effect, names imported by a using_namespace_directive are hidden by similarly named members in the enclosing compilation unit or namespace body.
Example:
namespace N1.N2 { class A {} class B {} } namespace N3 { using N1.N2; class A {} }
Здесь, в объявлениях членов в
N3
пространстве имен,A
ссылаетсяN3.A
на нееN1.N2.A
.end example
Because names may be ambiguous when more than one imported namespace introduces the same type name, a using_alias_directive is useful to disambiguate the reference.
Example: In the following code
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
нее является ошибкой во время компиляции. In this situation, the conflict can be resolved either through qualification of references toA
, or by introducing a using_alias_directive that picks a particularA
. For example:namespace N3 { using N1; using N2; using A = N1.A; class B : A {} // A means N1.A }
end example
Furthermore, when more than one namespace or type imported by using_namespace_directives or using_static_directives 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.
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
contains a type memberA
, andC
contains a static fieldA
, and becauseN2
imports both, referencingA
as a simple_name is ambiguous and a compile-time error.end example
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.
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. Thus, using_namespace_directives in the same compilation unit or namespace body do not affect each other and can be written in any order.
14.5.4 Использование статических директив
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 ';'
;
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.
Example:
namespace N1 { class A { public class B {} public static B M() => new B(); } } namespace N2 { using static N1.A; class C { void N() { B b = M(); } } }
В приведенном выше коде в объявлениях членов в
N2
пространстве имен статические члены и вложенные типыN1.A
доступны напрямую, поэтому методN
может ссылаться как наB
элементы, так иM
на элементыN1.A
.end example
A using_static_directive specifically does not import extension methods directly as static methods, but makes them available for extension method invocation (§12.8.10.3).
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 } } }
the using_static_directive imports the extension method
M
contained inN1.A
, but only as an extension method. Таким образом, первая ссылкаM
на текст результатов в результате ошибки во время компиляцииB.N
, так как именованныеM
элементы не находятся в области.end example
A using_static_directive only imports members and types declared directly in the given type, not members and types declared in base classes.
Example:
namespace N1 { class A { public static void M(string s){} } class B : A { public static void M2(string s){} } } namespace N2 { using static N1.B; class C { void N() { M2("B"); // OK, calls B.M2 M("C"); // Error. M unknown } } }
the using_static_directive imports the method
M2
contained inN1.B
, but does not import the methodM
contained inN1.A
. Таким образом, ссылка наM
текст результатов в результате ошибки во время компиляцииC.N
, так как именованныеM
элементы не находятся в области. Разработчики должны добавить вторуюusing static
директиву, чтобы указать, что методы вN1.A
ней также должны быть импортированы.end example
Ambiguities between multiple using_namespace_directives and using_static_directives are discussed in §14.5.3.
Объявления членов пространства имен 14.6
A namespace_member_declaration is either a namespace_declaration (§14.3) or a type_declaration (§14.7).
namespace_member_declaration
: namespace_declaration
| type_declaration
;
A compilation unit or a namespace body can contain namespace_member_declarations, and such declarations contribute new members to the underlying declaration space of the containing compilation unit or namespace body.
Объявления типов 14.7
A type_declaration is a class_declaration (§15.2), a struct_declaration (§16.2), an interface_declaration (§18.2), an enum_declaration (§19.2), or a delegate_declaration (§20.2).
type_declaration
: class_declaration
| struct_declaration
| interface_declaration
| enum_declaration
| delegate_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.
When a type declaration for a type T
occurs as a top-level declaration in a compilation unit, the fully qualified name (§7.8.3) of the type declaration is the same as the unqualified name of the declaration (§7.8.2). When a type declaration for a type T
occurs within a namespace, class, or struct declaration, the fully qualified name (§7.8.3) of the type declarationis S.N
, where S
is the fully qualified name of the containing namespace, class, or struct declaration, and N
is the unqualified name of the declaration.
A type declared within a class or struct is called a nested type (§15.3.9).
The permitted access modifiers and the default access for a type declaration depend on the context in which the declaration takes place (§7.5.2):
- Типы, объявленные в единицах компиляции или пространствах имен, могут иметь
public
илиinternal
получать доступ. По умолчанию используетсяinternal
доступ. - Типы, объявленные в классах, могут иметь
public
,protected internal
,protected
,private protected
internal
илиprivate
доступ. По умолчанию используетсяprivate
доступ. - Типы, объявленные в структуры, могут иметь
public
internal
илиprivate
получить доступ. По умолчанию используетсяprivate
доступ.
14.8 Квалифицированный псевдоним
14.8.1 General
Квалификатор ::
пространства имен позволяет гарантировать, что поиск имен типа не влияет на новые типы и члены. Квалификатор пространства имен всегда отображается между двумя идентификаторами, называемыми идентификаторами слева и правой рукой. В отличие от обычного .
квалификатора, левый идентификатор ::
квалификатора выглядит только как экстерн или использует псевдоним.
A qualified_alias_member provides explicit access to the global namespace and to extern or using aliases that are potentially hidden by other entities.
qualified_alias_member
: identifier '::' identifier type_argument_list?
;
A qualified_alias_member can be used as a namespace_or_type_name (§7.8) or as the left operand in a member_access (§12.8.7).
A qualified_alias_member consists of two identifiers, referred to as the left-hand and right-hand identifiers, seperated by the ::
token and optionally followed by a type_argument_list. Если идентификатор слева является глобальным, глобальный пространство имен выполняется поиск правого идентификатора. For any other left-hand identifier, that identifier is looked up as an extern or using alias (§14.4 and §14.5.2). Ошибка во время компиляции возникает, если такой псевдоним отсутствует или псевдоним ссылается на тип. Если псевдоним ссылается на пространство имен, то для этого пространства имен выполняется поиск правого идентификатора.
A qualified_alias_member has one of two forms:
-
N::I<A₁, ..., Aₑ>
, гдеN
иI
представляет идентификаторы и<A₁, ..., Aₑ>
является списком аргументов типа. (e
всегда один.) -
N::I
, гдеN
иI
представляет идентификаторы. (В этом случаеe
считается нулевой.)
Using this notation, the meaning of a qualified_alias_member is determined as follows:
- Если
N
это идентификаторglobal
, то глобальное пространство имен выполняется поиск по следующим причинамI
:- If the global namespace contains a namespace named
I
ande
is zero, then the qualified_alias_member refers to that namespace. - Otherwise, if the global namespace contains a non-generic type named
I
ande
is zero, then the qualified_alias_member refers to that type. - Otherwise, if the global namespace contains a type named
I
that hase
type parameters, then the qualified_alias_member refers to that type constructed with the given type arguments. - Otherwise, the qualified_alias_member is undefined and a compile-time error occurs.
- If the global namespace contains a namespace named
- Otherwise, starting with the namespace declaration (§14.3) 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:
- 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.
- Otherwise, if the namespace declaration or compilation unit contains an extern_alias_directive or using_alias_directive that associates
N
with a namespace, then:- If the namespace associated with
N
contains a namespace namedI
ande
is zero, then the qualified_alias_member refers to that namespace. - Otherwise, if the namespace associated with
N
contains a non-generic type namedI
ande
is zero, then the qualified_alias_member refers to that type. - Otherwise, if the namespace associated with
N
contains a type namedI
that hase
type parameters, then the qualified_alias_member refers to that type constructed with the given type arguments. - Otherwise, the qualified_alias_member is undefined and a compile-time error occurs.
- If the namespace associated with
- Otherwise, the qualified_alias_member is undefined and a compile-time error occurs.
Example: In the code:
using S = System.Net.Sockets; class A { public static int x; } class C { public void F(int A, object S) { // Use global::A.x instead of A.x global::A.x += A; // Use S::Socket instead of S.Socket S::Socket s = S as S::Socket; } }
Класс ссылается на этот класс
A
, а типglobal::A
ссылается наSystem.Net.Sockets.Socket
.S::Socket
ИспользованиеA.x
иS.Socket
вместо этого приводило бы к ошибкам во время компиляции, так какA
иS
было бы разрешено к параметрам.end example
Note: The identifier
global
has special meaning only when used as the left-hand identifier of a qualified_alias_name. It is not a keyword and it is not itself an alias; it is a contextual keyword (§6.4.4). В коде:class A { } class C { global.A x; // Error: global is not defined global::A y; // Valid: References A in the global namespace }
использование
global.A
вызывает ошибку во время компиляции, так как в области нет сущности, именуемойglobal
. Если бы некоторые сущности с именем global были в области, тоglobal
вglobal.A
этом объекте было бы разрешено.Using
global
as the left-hand identifier of a qualified_alias_member always causes a lookup in theglobal
namespace, even if there is a using alias namedglobal
. В коде:using global = MyGlobalTypes; class A { } class C { global.A x; // Valid: References MyGlobalTypes.A global::A y; // Valid: References A in the global namespace }
global.A
разрешает иMyGlobalTypes.A
global::A
разрешает классA
в глобальном пространстве имен.end note
14.8.2 Уникальность псевдонимов
Каждый блок компиляции и текст пространства имен имеет отдельное пространство объявлений для экстерн-псевдонимов и использование псевдонимов. Таким образом, в то время как имя экстерн-псевдонима или псевдонима должно быть уникальным в наборе экстерн-псевдонимов и использовать псевдонимы, объявленные в немедленном элементе компиляции или теле пространства имен, псевдоним может иметь то же имя, что и тип или пространство имен, если он используется только с квалификатором ::
.
Example: In the following:
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
и псевдонимA
используются в области. По этой причине использованиеA
в квалифицированном имениA.Stream
неоднозначно и приводит к возникновению ошибки во время компиляции. Однако использованиеA
с::
квалификатором не является ошибкой, так какA
ищется только в качестве псевдонима пространства имен.end example
ECMA C# draft specification