Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp Language Specification.doc
Скачиваний:
13
Добавлен:
26.09.2019
Размер:
4.75 Mб
Скачать

9.3Внешние псевдонимы

Директива_extern_alias вводит идентификатор, служащий псевдонимом пространства имен. Спецификация пространства имен с псевдонимом является внешней по отношению к исходному коду программы и применяется также к вложенным пространствам имен пространства имен с псевдонимом.

директивы_внешних_псевдонимов: директива_внешнего_псевдонима директивы_внешних_псевдонимов директива_внешнего_псевдонима

директива_extern_alias: extern alias идентификатор ;

Область директивы_extern_alias распространяется на директивы_using, глобальные_атрибуты и объявления_членов_пространства_имен в непосредственно содержащей ее единице компиляции или теле пространства имен.

Внутри единицы компиляции или в теле пространства имен, содержащем директиву_ extern-alias, идентификатор, введенный директивой_ extern-alias, можно использовать для ссылки на пространство имен с псевдонимом. Если в качестве идентификатора использовать слово global, произойдет ошибка времени компиляции.

Директива_extern_alias делает псевдоним доступным внутри отдельной единицы компиляции или тела пространства имен, но не размещает новые члены в базовой области объявлений. Иначе говоря, директива_extern_alias не является транзитивной, и влияет только на единицу компиляции или тело пространства имен, в котором находится.

В следующей программе объявляются и используются два внешних псевдонима, 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. Если в программе объявлен внешний псевдоним, для которого не дано внешнее определение, происходит ошибка.

9.4Директивы using

Директивы using упрощают использование пространств имен и типов, определенных в других пространствах имен. Директивы using влияют на процесс разрешения имен_пространств_имен_или_типов (§3.8) и простых_имен (§7.6.2), но, в отличие от объявлений, директивы using не размещают новые члены в базовых областях объявлений единиц компиляции или пространств имен, в которых они использованы.

директивы_using: директива_using директивы_using директива_using

директива_using: директива_using_alias директива_using_namespace

Директива_using_alias (§9.4.1) вводит псевдоним для пространства имен или типа.

Директива_using_namespace (§9.4.2) импортирует члены типа пространства имен.

Область директивы_using распространяется на объявления_членов_пространства_имен непосредственно содержащей ее единицы компиляции или тела пространства имен. Область видимости директивы_using не включает одноуровневые директивы_using. Таким образом, одноуровневые директивы_using не влияют друг на друга и могут быть записаны в любом порядке.

9.4.1Директивы using alias

Директива_using_alias вводит идентификатор, служащий псевдонимом для пространства имен или типа внутри непосредственно вмещающей единицы компиляции или тела пространства имен.

директива_using_alias: using идентификатор = имя_пространства_имен_или_типа ;

Внутри объявлений членов в единице компиляции или в теле пространства имен, содержащем директиву_using_alias, идентификатор, введенный директивой_using_alias, можно использовать для ссылки на данное пространство имен или тип. Например:

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 {} }

Идентификатор в директиве_using_alias должен быть уникальным внутри области объявлений единицы компиляции или пространства имен, непосредственно содержащих директиву_using_alias. Например:

namespace N3 { class A {} }

namespace N3 { using A = N1.N2.A; // Error, A already exists }

В приведенном примере N3 уже содержит член A, поэтому использование этого идентификатора в директиве_using_alias вызовет ошибку времени компиляции. Аналогично, произойдет ошибка времени компиляции, если две или более директивы_using_alias в одной и той же единице компиляции или пространстве имен объявляют псевдонимы с одним и тем же именем.

Директива_using_alias делает псевдоним доступным внутри отдельной единицы компиляции или тела пространства имен, но не размещает новые члены в базовой области объявлений. Иначе говоря, директива_using_alias не является транзитивной, и влияет только на единицу компиляции или тело пространства имен, в котором находится. В этом примере

namespace N3 { using R = N1.N2; }

namespace N3 { class B: R.A {} // Error, R unknown }

область директивы_using_alias, которая вводит R, распространяется только на объявления членов в теле пространства имен, в котором она содержится, так что R неизвестно в объявлении второго пространства имен. Однако если поместить директиву_using_alias в содержащую единицу компиляции, то этот псевдоним будет доступен внутри обоих объявлений пространств имен:

using R = N1.N2;

namespace N3 { class B: R.A {} }

namespace N3 { class C: R.A {} }

Как и регулярные члены, имена, введенные директивой_using_alias, скрыты членами с таким же именем во вложенных областях. В этом примере

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.

Порядок, в котором записаны директивы_using_alias, не имеет значения, а на разрешение имени_пространства_имен_или_типа, на которое ссылается директива_using_alias, не влияет ни сама директива_using_alias, ни другие директивы_using в непосредственно содержащей единице компиляции или теле пространства имен. Другими словами, имя_пространства_имен_или_типа директивы_using_alias разрешается, если непосредственно содержащая единица компиляции или тело пространства имен не имеет директивы_using. На директиву_using_alias могут повлиять директивы_extern_alias в непосредственно содержащей единице компиляции или теле пространства имен. В этом примере

namespace N1.N2 {}

namespace N3 { extern alias E;

using R1 = E.N; // OK

using R2 = N1; // OK

using R3 = N1.N2; // OK

using R4 = R2.N2; // Error, R2 unknown }

последняя директива_using_alias приводит к ошибке времени компиляции, так как на нее не влияет первая директива_using_alias. Первая директива_using_alias не приводит к ошибке, поскольку область внешнего псевдонима E включает директиву_using_alias.

Директивой_using_alias можно создать псевдоним для любого пространства имен или типа, включая пространство имен, внутри которого она находится, и любое пространство имен или тип, вложенные в это пространство имен.

Доступ к пространству имен или типу через псевдоним дает точно такой же результат, как доступ к этому пространству имен или типу через его объявленное имя. Например, если дана

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.

С помощью псевдонимов можно именовать закрытый сформированный тип, но нельзя именовать объявление несвязанного универсального типа, не предоставляя аргументы типа. Например:

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 }

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]