Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
14.1 Общие
Программы C# упорядочены с помощью пространств имен. Пространства имен используются как в качестве внутренней системы организации для программы, так и как внешняя система организации — способ представления элементов программы, предоставляемых другим программам.
Директивы using (§14.5) предоставляются для упрощения использования пространств имен.
Единицы компиляции 14.2
Compilation_unit состоит из нуля или болееextern_alias_directive, за которым следует нулевая или более using_directive, а затем нулю или одному global_attributes, а затем нулю или более namespace_member_declaration. Compilation_unit определяет общую структуру входных данных.
compilation_unit
: extern_alias_directive* using_directive* global_attributes?
namespace_member_declaration*
;
Программа C# состоит из одного или нескольких единиц компиляции. При компиляции программы C# все единицы компиляции обрабатываются вместе. Таким образом, единицы компиляции могут зависеть друг от друга, возможно, в циклической форме.
Extern_alias_directiveединиц компиляции влияют на using_directive, global_attributes и namespace_member_declarationэтого модуля компиляции, но не влияют на другие единицы компиляции.
Using_directiveединиц компиляции влияют на global_attributes и namespace_member_declarationэтого модуля компиляции, но не влияют на другие единицы компиляции.
Global_attributes (§23.3) единицы компиляции позволяют спецификации атрибутов целевой сборки и модуля. Сборки и модули служат физическими контейнерами для типов. Сборка может состоять из нескольких физически отдельных модулей.
Namespace_member_declarationкаждой единицы компиляции программы вносят свой вклад в одно пространство объявлений, называемое глобальным пространством имен.
Example:
// File A.cs: class A {} // File B.cs: class B {}Два единицы компиляции способствуют одному глобальному пространству имен, в этом случае объявляя два класса с полными именами
AиB. Так как два единици компиляции способствуют одному и тому же пространству объявлений, это было бы ошибкой, если каждая из них содержала объявление члена с одинаковым именем.конечный пример
Объявления пространства имен 14.3
Namespace_declaration состоит из пространства имен ключевых слов, за которым следует имя пространства имен и текст, а также запятой.
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. Когда namespace_declaration происходит как объявление верхнего уровня в compilation_unit, пространство имен становится членом глобального пространства имен. Когда namespace_declaration происходит в другом namespace_declaration, внутреннее пространство имен становится членом внешнего пространства имен. В любом случае имя пространства имен должно быть уникальным в пределах содержащего пространства имен.
Пространства имен неявно public и объявление пространства имен не может включать модификаторы доступа.
В namespace_body необязательный using_directiveимпортирует имена других пространств имен, типов и членов, что позволяет ссылаться на них напрямую, а не через квалифицированные имена. Необязательные namespace_member_declarationвносят свой вклад в пространство объявления пространства имен. Обратите внимание, что все using_directives должны отображаться перед объявлениями членов.
Qualified_identifier namespace_declaration может быть одним идентификатором или последовательностью идентификаторов, разделенных. "" маркерами. Последняя форма позволяет программе определять вложенное пространство имен без лексического вложения нескольких объявлений пространства имен.
Example:
namespace N1.N2 { class A {} class B {} }семантически эквивалентен
namespace N1 { namespace N2 { class A {} class B {} } }конечный пример
Пространства имен открыты, и два объявления пространства имен с одинаковым полным именем (§7.8.3) вносят вклад в одно и то же пространство объявлений (§7.3).
Пример. В следующем коде
namespace N1.N2 { class A {} } namespace N1.N2 { class B {} }Два объявления пространства имен, приведенные выше, способствуют одному и тому же пространству объявлений, в этом случае объявляя два класса с полными именами
N1.N2.AиN1.N2.B. Так как два объявления способствуют одному и тому же пространству объявлений, это было бы ошибкой, если каждая из них содержала объявление члена с одинаковым именем.конечный пример
Директивы псевдонима Extern 14.4
В extern_alias_directive представлен идентификатор, который служит псевдонимом для пространства имен. Спецификация псевдонима пространства имен является внешней к исходному коду программы и применяется также к вложенным пространствам имен псевдонима пространства имен.
extern_alias_directive
: 'extern' 'alias' identifier ';'
;
Область extern_alias_directive распространяется на using_directive s,global_attributes и namespace_member_declarationего немедленной compilation_unit или namespace_body.
В блоке компиляции или тексте пространства имен, содержащего extern_alias_directive, идентификатор, представленный extern_alias_directive , можно использовать для ссылки на псевдонимное пространство имен. Это ошибка во время компиляции для идентификатора , который должен быть словом global.
Псевдоним, представленный extern_alias_directive , очень похож на псевдоним, представленный using_alias_directive. Дополнительные сведения о extern_alias_directiveи using_alias_directiveсм. в статье 14.5.2.
alias — это контекстное ключевое слово (§6.4.4) и имеет особое значение только при немедленном выполнении extern ключевого слова в extern_alias_directive.
Ошибка возникает, если программа объявляет экстерн-псевдоним, для которого отсутствует внешнее определение.
Пример: следующая программа объявляет и использует два экстерна псевдонима,
XиYкаждый из которых представляет корень отдельной иерархии пространства имен: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. конечный пример
Директивы using 14.5
14.5.1 Общие
Директива using упрощает использование пространств имен и типов, определенных в других пространствах имен. Использование директив влияет на процесс разрешения имен namespace_or_type_name(§7.8) и simple_names (§12.8.4), но в отличие от объявлений, using_directiveне вносят новых членов в базовые пространства объявлений единиц компиляции или пространств имен, в которых они используются.
using_directive
: using_alias_directive
| using_namespace_directive
| using_static_directive
;
В using_alias_directive (§14.5.2) представлен псевдоним пространства имен или типа.
Using_namespace_directive (§14.5.3) импортирует элементы типа пространства имен.
Using_static_directive (§14.5.4) импортирует вложенные типы и статические элементы типа.
Область using_directive расширяется по namespace_member_declarations его немедленного элемента компиляции или тела пространства имен. Область using_directive , в частности, не включает его одноранговые using_directive. Таким образом, одноранговые using_directiveне влияют друг на друга, а порядок их записи незначительный. В отличие от этого, область extern_alias_directive включает using_directive, определенные в том же модуле компиляции или теле пространства имен.
14.5.2 Использование директив псевдонима
Using_alias_directive представляет идентификатор, который служит псевдонимом для пространства имен или типа в пределах немедленного заключающего блока компиляции или текста пространства имен.
using_alias_directive
: 'using' identifier '=' namespace_or_type_name ';'
;
В глобальных атрибутах и объявлениях членов в блоке компиляции или тексте пространства имен, содержащего using_alias_directive, идентификатор, представленный using_alias_directive , можно использовать для ссылки на заданное пространство имен или тип.
Example:
namespace N1.N2 { class A {} } namespace N3 { using A = N1.N2.A; class B: A {} }Выше в объявлениях членов в
N3пространстве имен используется псевдоним,Aпоэтому классN1.N2.Aявляется производным от классаN3.BN1.N2.A. Тот же эффект можно получить путем создания псевдонимаRдляN1.N2и последующегоR.Aссылки:namespace N3 { using R = N1.N2; class B : R.A {} }конечный пример
В директивах, глобальных атрибутах и объявлениях членов в блоке компиляции или тексте пространства имен, содержащего extern_alias_directive, идентификатор, представленный extern_alias_directive , можно использовать для ссылки на связанное пространство имен.
Пример: например:
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 {} }конечный пример
Extern_alias_directive или using_alias_directive делает псевдоним доступным в определенном блоке компиляции или теле пространства имен, но не вносит новых членов в базовое пространство объявления. Другими словами, директива псевдонима не является транзитивной, но, скорее, влияет только на блок компиляции или тело пространства имен, в котором она происходит.
Пример. В следующем коде
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 {} }конечный пример
Каждый extern_alias_directive или using_alias_directive в compilation_unit или namespace_body вносит имя в пространство объявления псевдонима (§7.3) немедленно заключающего compilation_unit или namespace_body. Идентификатор директивы псевдонима должен быть уникальным в соответствующем пространстве объявления псевдонима. Идентификатор псевдонима не должен быть уникальным в пределах глобального пространства объявлений или пространства объявления соответствующего пространства имен.
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; аналогично.AN3.BКласс можно ссылаться какN3.Bилиglobal::N3.B. Псевдоним можно использовать вA(§14.8), напримерA::B. ПсевдонимBпо сути бесполезен. Его нельзя использовать в qualified_alias_member , так как только псевдонимы пространства имен можно использовать в qualified_alias_member иBпсевдонимах типа.конечный пример
Как и обычные элементы, имена, представленные alias_directives , скрыты аналогичным именованным элементами в вложенных областях.
Пример. В следующем коде
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конечный пример
Порядок записи extern_alias_directiveне имеет значения. Аналогичным образом, порядок записи using_alias_directiveне имеет значения, но все using_alias_directives должны поступать после всех extern_alias_directiveв одном блоке компиляции или теле пространства имен. Разрешение namespace_or_type_name , на который ссылается using_alias_directive , не влияет на сам using_alias_directive или другие using_directiveв немедленном блоке компиляции или теле пространства имен, но могут быть затронуты extern_alias_directiveв немедленном блоке компиляции или теле пространства имен. Другими словами, namespace_or_type_name using_alias_directive разрешается так, как если бы немедленно содержащий модуль компиляции или текст пространства имен не имел using_directives, но имеет правильный набор extern_alias_directives.
Пример. В следующем коде
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 }Последняя using_alias_directive приводит к ошибке во время компиляции, так как она не влияет на предыдущие using_alias_directive. Первый using_alias_directive не приводит к ошибке, так как область действия экстерн-псевдонима X включает using_alias_directive.
конечный пример
Using_alias_directive может создать псевдоним для любого пространства имен или типа, включая пространство имен, в котором она отображается, и любое пространство имен или тип, вложенные в это пространство имен.
Доступ к пространству имен или типу с помощью псевдонима дает точно тот же результат, что и доступ к пространству имен или типу через объявленное имя.
Пример: задано
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конечный пример
Хотя каждая часть частичного типа (§15.2.7) объявлена в одном пространстве имен, части обычно записываются в разных объявлениях пространства имен. Таким образом, для каждой части могут присутствовать разные extern_alias_directiveи using_directive. При интерпретации простых имен (§12.8.4) в одной части рассматриваются только extern_alias_directiveи using_directiveтел пространства имен и единиц компиляции, заключающих ее. Это может привести к тому, что один и тот же идентификатор имеет разные значения в разных частях.
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 } }конечный пример
Используя псевдонимы, можно назвать закрытый созданный тип, но не удается назвать объявление универсального типа без указания аргументов типа.
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 }конечный пример
14.5.3 С помощью директив пространства имен
Using_namespace_directive импортирует типы, содержащиеся в пространстве имен, в немедленно заключив блок компиляции или текст пространства имен, что позволяет использовать идентификатор каждого типа без квалификации.
using_namespace_directive
: 'using' namespace_name ';'
;
В объявлениях членов в тексте модуля компиляции или пространства имен, содержащего using_namespace_directive, можно ссылаться непосредственно на типы, содержащиеся в заданном пространстве имен.
Example:
namespace N1.N2 { class A {} } namespace N3 { using N1.N2; class B : A {} }Выше в объявлениях членов в
N3пространстве имен членыN1.N2члены являются доступными напрямую и таким образом классN3.Bявляется производным от классаN1.N2.A.конечный пример
Using_namespace_directive импортирует типы, содержащиеся в заданном пространстве имен, но в частности не импортируют вложенные пространства имен.
Пример. В следующем коде
namespace N1.N2 { class A {} } namespace N3 { using N1; class B : N2.A {} // Error, N2 unknown }using_namespace_directive импортирует типы, содержащиеся в
N1, но не пространства имен, вложенные вN1. Таким образом, ссылка наN2.Aобъявление приводит к ошибке во время компиляцииB, так как именованныеN2элементы не находятся в области.конечный пример
В отличие от using_alias_directive, using_namespace_directive может импортировать типы, идентификаторы которых уже определены в блоке компиляции или теле пространства имен. Фактически имена, импортированные using_namespace_directive , скрыты аналогичными именованными элементами в блоке компиляции или тексте пространства имен.
Example:
namespace N1.N2 { class A {} class B {} } namespace N3 { using N1.N2; class A {} }Здесь, в объявлениях членов в
N3пространстве имен,AссылаетсяN3.Aна нееN1.N2.A.конечный пример
Поскольку имена могут быть неоднозначными, если несколько импортированных пространств имен вводят одно и то же имя типа, using_alias_directive полезно для диамбигуации ссылки.
Пример. В следующем коде
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нее является ошибкой во время компиляции. В этой ситуации конфликт может быть разрешен либо с помощью квалификации ссылокAна , либо путем введения using_alias_directive , который выбирает конкретныйA. Рассмотрим пример.namespace N3 { using N1; using N2; using A = N1.A; class B : A {} // A means N1.A }конечный пример
Кроме того, если несколько пространств имен или типов импортируются using_namespace_directiveили using_static_directiveв одном модуле компиляции или тексте пространства имен содержат типы или члены с тем же именем, ссылки на это имя как simple_name считаются неоднозначными.
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содержит элементAтипа и содержит статическое полеC, иAтак какN2импортирует оба, ссылкаAкак simple_name является неоднозначной и ошибкой во время компиляции.конечный пример
Как и using_alias_directive, using_namespace_directive не вносит новых членов в базовое пространство объявления единицы компиляции или пространства имен, но, скорее, влияет только на единицу компиляции или тело пространства имен, в котором она отображается.
Namespace_name, на который ссылается using_namespace_directive, разрешается так же, как и namespace_or_type_name, на которые ссылается using_alias_directive. Таким образом, using_namespace_directiveв одном блоке компиляции или теле пространства имен не влияют друг на друга и могут быть записаны в любом порядке.
14.5.4 Использование статических директив
Using_static_directive импортирует вложенные типы и статические члены, содержащиеся непосредственно в объявлении типа, в немедленно заключив блок компиляции или тело пространства имен, что позволяет использовать идентификатор каждого элемента и типа без квалификации.
using_static_directive
: 'using' 'static' type_name ';'
;
В объявлениях членов в тексте модуля компиляции или пространства имен, содержащего using_static_directive, доступные вложенные типы и статические члены (кроме методов расширения), содержащиеся непосредственно в объявлении данного типа, можно ссылаться напрямую.
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.конечный пример
Using_static_directive специально не импортирует методы расширения непосредственно как статические методы, но делает их доступными для вызова метода расширения (§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 } } }using_static_directive импортирует метод
Mрасширения, содержащийся вN1.A, но только в качестве метода расширения. Таким образом, первая ссылкаMна текст результатов в результате ошибки во время компиляцииB.N, так как именованныеMэлементы не находятся в области.конечный пример
Using_static_directive импортирует только элементы и типы, объявленные непосредственно в данном типе, а не члены и типы, объявленные в базовых классах.
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 } } }using_static_directive импортирует метод, содержащийся в
M2, но не импортирует методN1.BM, содержащийся вN1.A. Таким образом, ссылка наMтекст результатов в результате ошибки во время компиляцииC.N, так как именованныеMэлементы не находятся в области. Разработчики должны добавить вторуюusing staticдирективу, чтобы указать, что методы вN1.Aней также должны быть импортированы.конечный пример
Неоднозначность между несколькими using_namespace_directives и using_static_directives обсуждаются в §14.5.3.
Объявления членов пространства имен 14.6
Namespace_member_declaration — это namespace_declaration (§14.3) или type_declaration (§14.7).
namespace_member_declaration
: namespace_declaration
| type_declaration
;
Единица компиляции или текст пространства имен может содержать namespace_member_declarations, и такие объявления вносят новые члены в базовое пространство объявления содержащего единицы компиляции или тела пространства имен.
Объявления типов 14.7
Type_declaration — это class_declaration (§15.2), struct_declaration (§16.2), interface_declaration (§19.2), enum_declaration (§20.2) или delegate_declaration (§21.2).
type_declaration
: class_declaration
| struct_declaration
| interface_declaration
| enum_declaration
| delegate_declaration
;
Type_declaration может возникать в виде объявления верхнего уровня в единице компиляции или в виде объявления члена в пространстве имен, классе или структуре.
Когда объявление типа для типа происходит в виде объявления верхнего уровня в единице компиляции, полное имя (T) объявления типа совпадает с неквалифицированным именем объявления (§7.8.2). Если объявление типа для типа T происходит в пространстве имен, классе или объявлении структуры, полное имя (§7.8.3) объявления S.Nтипа , где S является полное имя содержащего пространства имен, класса или объявления структуры, а также N является неквалифицированным именем объявления объявления.
Тип, объявленный в классе, интерфейсе или структуре, называется вложенным типом (§15.3.9).
Модификаторы разрешенного доступа и доступ по умолчанию для объявления типа зависят от контекста, в котором происходит объявление (§7.5.2):
- Типы, объявленные в единицах компиляции или пространствах имен, могут иметь
publicилиinternalполучать доступ. По умолчанию используетсяinternalдоступ. - Типы, объявленные в классах, могут иметь
public,protected internal,protected,private protectedinternalилиprivateдоступ. По умолчанию используетсяprivateдоступ. - Типы, объявленные в структуры, могут иметь
publicinternalилиprivateполучить доступ. По умолчанию используетсяprivateдоступ.
14.8 Квалифицированный псевдоним
14.8.1 Общие
Квалификатор :: пространства имен позволяет гарантировать, что поиск имен типа не влияет на новые типы и члены. Квалификатор пространства имен всегда отображается между двумя идентификаторами, называемыми идентификаторами слева и правой рукой. В отличие от обычного . квалификатора, левый идентификатор :: квалификатора выглядит только как экстерн или использует псевдоним.
Qualified_alias_member предоставляет явный доступ к глобальному пространству имен и к экстерну или использованию псевдонимов, которые потенциально скрыты другими сущностями.
qualified_alias_member
: identifier '::' identifier type_argument_list?
;
Qualified_alias_member можно использовать в качестве namespace_or_type_name (§7.8) или в качестве левого операнда в member_access (§12.8.7).
Qualified_alias_member состоит из двух идентификаторов, называемых идентификаторами слева и правой рукой, разделяемым :: маркером и при необходимости type_argument_list. Если идентификатор слева является глобальным, глобальный пространство имен выполняется поиск правого идентификатора. Для любого другого левого идентификатора этот идентификатор выглядит как экстерн или использует псевдоним (§14.4 и §14.5.2). Ошибка во время компиляции возникает, если такой псевдоним отсутствует или псевдоним ссылается на тип. Если псевдоним ссылается на пространство имен, то для этого пространства имен выполняется поиск правого идентификатора.
Qualified_alias_member имеет одну из двух форм:
-
N::I<A₁, ..., Aₑ>, гдеNиIпредставляет идентификаторы и<A₁, ..., Aₑ>является списком аргументов типа. (eвсегда один.) -
N::I, гдеNиIпредставляет идентификаторы. (В этом случаеeсчитается нулевой.)
Используя эту нотацию, значение qualified_alias_member определяется следующим образом:
- Если
Nэто идентификаторglobal, то глобальное пространство имен выполняется поиск по следующим причинамI:- Если глобальное пространство имен содержит пространство имен и
Ieравно нулю, то qualified_alias_member ссылается на это пространство имен. - В противном случае, если глобальное пространство имен содержит не универсальный тип с именем
Iиeравно нулю, то qualified_alias_member ссылается на этот тип. - В противном случае, если глобальное пространство имен содержит тип с
Ieпараметрами типа, то qualified_alias_member ссылается на этот тип, созданный с заданными аргументами типа. - В противном случае qualified_alias_member не определен и возникает ошибка во время компиляции.
- Если глобальное пространство имен содержит пространство имен и
- В противном случае, начиная с объявления пространства имен (§14.3) сразу же, содержащего qualified_alias_member (если таковые есть), продолжая каждое объявление пространства имен (если есть), и заканчивая единицей компиляции, содержащей qualified_alias_member, следующие шаги оцениваются до тех пор, пока сущность не будет найдена:
- Если объявление пространства имен или единица компиляции содержит using_alias_directive , которая связывает N с типом, qualified_alias_member не определена, и возникает ошибка во время компиляции.
- В противном случае, если объявление пространства имен или единица компиляции содержит extern_alias_directive или using_alias_directive , которая связывается
Nс пространством имен, то:- Если пространство имен, связанное с
Nним, содержит пространство имен иIeравно нулю, то qualified_alias_member ссылается на это пространство имен. - В противном случае, если пространство имен
N, связанное сIним, содержит не универсальный тип иeравно нулю, то qualified_alias_member ссылается на этот тип. - В противном случае, если пространство имен, связанное с
Nним, содержит тип сIeпараметрами типа, то qualified_alias_member ссылается на этот тип, созданный с заданными аргументами типа. - В противном случае qualified_alias_member не определен и возникает ошибка во время компиляции.
- Если пространство имен, связанное с
- В противном случае qualified_alias_member не определен и возникает ошибка во время компиляции.
Пример. В коде:
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было бы разрешено к параметрам.конечный пример
Примечание. Идентификатор
globalимеет особое значение, только если используется в качестве левого идентификатора qualified_alias_name. Это не ключевое слово, и это не сам псевдоним; это контекстное ключевое слово (§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этом объекте было бы разрешено.Использование
globalв качестве левого идентификатора qualified_alias_member всегда вызывает поиск вglobalпространстве имен, даже если псевдоним используетсяglobal. В коде: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.Aglobal::Aразрешает классAв глобальном пространстве имен.конечная заметка
14.8.2 Уникальность псевдонимов
Каждый блок компиляции и текст пространства имен имеет отдельное пространство объявлений для экстерн-псевдонимов и использование псевдонимов. Таким образом, в то время как имя экстерн-псевдонима или псевдонима должно быть уникальным в наборе экстерн-псевдонимов и использовать псевдонимы, объявленные в немедленном элементе компиляции или теле пространства имен, псевдоним может иметь то же имя, что и тип или пространство имен, если он используется только с квалификатором :: .
Пример. В следующем примере:
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ищется только в качестве псевдонима пространства имен.конечный пример
ECMA C# draft specification