Чтение онлайн

на главную - закладки

Жанры

Полное руководство. С# 4.0
Шрифт:

Одно пространство имен может быть вложено в другое. В качестве примера рас смотрим следующую программу. // Вложенные пространства имен. using System; namespace NS1 { class ClassA { public ClassA { Console.WriteLine("Конструирование класса ClassA"); } } namespace NS2 { // вложенное пространство имен class ClassB { public ClassB { Console.WriteLine("Конструирование класса ClassB"); } } } } class NestedNSDemo { static void Main { NS1.ClassA a = new NS1.ClassA; // NS2.ClassB b = new NS2.ClassB; // Неверно!!! Пространство NS2 невидимо NS1.NS2.ClassB b = new NS1.NS2.ClassB; // Верно! } }

Выполнение этой программы дает следующий результат. Конструирование класса ClassA Конструирование класса ClassB

В этой программе пространство

имен NS2 вложено в пространство имен NS1. По этому для обращения к классу ClassB необходимо дополнительно указать простран ства имен NS1 и NS2. Указания одного лишь пространства имен NS2 для этого недоста точно. Как следует из приведенного выше примера, пространства имен дополнитель но указываются через точку. Следовательно, для обращения к классу ClassB в методе Main необходимо указать его полное имя — NS1.NS2.ClassB.

Пространства имен могут быть вложенными больше, чем на два уровня. В этом слу чае член вложенного пространства имен должен быть дополнительно определен с по мощью всех охватывающих пространств имен.

Вложенные пространства имен можно указать в одном операторе namespace, раз делив их точкой. Например, вложенные пространства имен namespace OuterNS { namespace InnerNS { // ... } }

могут быть указаны следующим образом. namespace OuterNS.InnerNS { // ... } Глобальное пространство имен

Если в программе не объявлено пространство имен, то по умолчанию используется глобальное пространство имен. Именно поэтому в примерах программ, представлен ных в предыдущих главах книги, не нужно было обращаться для этой цели к клю чевому слову namespace. Глобальное пространство удобно для коротких программ, как в примерах из этой книги, но в большинстве случаев реальный код содержится в объявляемом пространстве имен. Главная причина инкапсуляции кода в объявляемом пространстве имен — предотвращение конфликтов имен. Пространства имен служат дополнительным средством, помогающим улучшить организацию программ и при способить их к работе в сложной среде с современной сетевой структурой. Применение описателя псевдонима пространства имен ::

Пространства имен помогают предотвратить конфликты имен, но не устранить их полностью. Такой конфликт может, в частности, произойти, когда одно и то же имя объявляется в двух разных пространствах имен и затем предпринимается попытка сделать видимыми оба пространства. Допустим, что два пространства имен содержат класс MyClass. Если попытаться сделать видимыми оба пространства имен с помо щью директив using, то имя MyClass из первого пространства вступит в конфликт с именем MyClass из второго пространства, обусловив появление ошибки неоднознач ности. В таком случае для указания предполагаемого пространства имен явным обра зом можно воспользоваться описателем псевдонима пространства имен ::.

Ниже приведена общая форма оператора ::. псевдоним_пространства_имен::идентификатор

Здесь псевдонимпространстваимен обозначает конкретное имя псевдонима про странства имен, а идентификатор — имя члена этого пространства.

Для того чтобы стало понятнее назначение описателя псевдонима пространства имен, рассмотрим следующий пример программы, в которой создаются два простран ства имен, Counter и AnotherCounter, и в обоих пространствах объявляется класс CountDown. Затем оба пространства имен становятся видимыми с помощью директив using. И наконец, в методе Main предпринимается попытка получить экземпляр объекта типа CountDown. // Продемонстрировать необходимость описателя ::. using System; // Использовать оба пространства имен Counter и AnotherCounter. using Counter; using AnotherCounter; // Объявить пространство имен для счетчиков. namespace Counter { // Простой вычитающий счетчик. class CountDown { int val; public CountDown(int n) { val = n; } // ... } } // Объявить еще одно пространство имен для счетчиков. namespace AnotherCounter { //

Объявить еще один класс CountDown, принадлежащий // пространству имен AnotherCounter. class CountDown { int val; public CountDown(int n) { val = n; } // ... } } class WhyAliasQualifier { static void Main { int i; // Следующая строка, по существу, неоднозначна! // Неясно, делается ли в ней ссылка на класс CountDown // из пространства имен Counter или AnotherCounter? CountDown cd1 = new CountDown(10); // Ошибка! ! ! // ... } }

Если попытаться скомпилировать эту программу, то будет получено сообщение об ошибке, уведомляющее о неоднозначности в следующей строке кода из метода Main. CountDown cd1 = new CountDown(10); // Ошибка!!!

Причина подобной неоднозначности заключается в том, что в обоих пространствах имен, Counter и AnotherCounter, объявлен класс CountDown и оба пространства сделаны видимыми. Поэтому неясно, к какому именно варианту класса CountDown следует отнести приведенное выше объявление. Для устранения подобного рода недо разумений и предназначен описатель ::.

Для того чтобы воспользоваться описателем ::, необходимо сначала определить псевдоним для пространства имен, которое требуется описать, а затем дополнить опи сание неоднозначного элемента этим псевдонимом. Ниже приведен вариант преды дущего примера программы, в котором устраняется упомянутая выше неоднознач ность. // Продемонстрировать применение описателя ::. using System; using Counter; using AnotherCounter; // Присвоить классу Counter псевдоним Ctr. using Ctr = Counter; // Объявить пространство имен для счетчиков. namespace Counter { // Простой вычитающий счетчик. class CountDown { int val; public CountDown(int n) { val = n; } // ... } } // Объявить еще одно пространство имен для счетчиков. namespace AnotherCounter { // Объявить еще один класс CountDown, принадлежащий // пространству имен AnotherCounter. class CountDown { int val; public CountDown(int n) { val = n; } // ... } } class AliasQualifierDemo { static void Main { // Здесь оператор :: разрешает конфликт, предписывая компилятору // использовать класс CountDown из пространства имен Counter. Ctr::CountDown cd1 = new Ctr::CountDown(10); // ... } }

В этом варианте программы для класса Counter сначала указывается псевдоним Ctr в следующей строке кода. using Ctr = Counter;

А затем этот псевдоним используется в методе Main для дополнительного опи сания класса CountDown, как показано ниже. Ctr::CountDown cd1 = new Ctr::CountDown(10);

Описатель :: устраняет неоднозначность, поскольку он явно указывает на то, что следует обратиться к классу CountDown из пространства Ctr, а фактически — Counter. Именно это и делает теперь программу пригодной для компиляции.

Описатель :: можно также использовать вместе с предопределенным идентифика тором global для ссылки на глобальное пространство имен. Например, в приведен ной ниже программе класс CountDown объявляется как в пространстве имен Counter, так и в глобальном пространстве имен. А для доступа к варианту класса CountDown в глобальном пространстве имен служит предопределенный псевдоним global. // Использовать псевдоним глобального пространства имен. using System; // Присвоить классу Counter псевдоним Ctr. using Ctr = Counter; // Объявить пространство имен для счетчиков. namespace Counter { // Простой вычитающий счетчик. class CountDown { int val; public CountDown(int n) { val = n; } // ... } } // Объявить еще один класс CountDown, принадлежащий // глобальному пространству имен. class CountDown { int val; public CountDown(int n) { val = n; } // ... } class GlobalAliasQualifierDemo { static void Main { // Здесь описатель :: предписывает компилятору использовать // класс CountDown из пространства имен Counter. Ctr::CountDown cd1 = new Ctr::CountDown(10); // Далее создать объект класса CountDown из // глобального пространства имен. global::CountDown cd2 = new global::CountDown(10); // ... } }

Поделиться:
Популярные книги

Хозяйка старой пасеки

Шнейдер Наталья
Фантастика:
попаданцы
фэнтези
7.50
рейтинг книги
Хозяйка старой пасеки

Измена. Не прощу

Леманн Анастасия
1. Измены
Любовные романы:
современные любовные романы
4.00
рейтинг книги
Измена. Не прощу

Черный маг императора 2

Герда Александр
2. Черный маг императора
Фантастика:
юмористическая фантастика
попаданцы
аниме
6.00
рейтинг книги
Черный маг императора 2

Разбуди меня

Рам Янка
7. Серьёзные мальчики в форме
Любовные романы:
современные любовные романы
остросюжетные любовные романы
5.00
рейтинг книги
Разбуди меня

Не грози Дубровскому! Том III

Панарин Антон
3. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том III

Семья. Измена. Развод

Высоцкая Мария Николаевна
2. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Семья. Измена. Развод

Хозяин Теней 4

Петров Максим Николаевич
4. Безбожник
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Хозяин Теней 4

Сердце Дракона. Том 9

Клеванский Кирилл Сергеевич
9. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.69
рейтинг книги
Сердце Дракона. Том 9

Потомок бога

Решетов Евгений Валерьевич
1. Локки
Фантастика:
попаданцы
альтернативная история
аниме
сказочная фантастика
5.00
рейтинг книги
Потомок бога

Отмороженный 11.0

Гарцевич Евгений Александрович
11. Отмороженный
Фантастика:
боевая фантастика
рпг
попаданцы
фантастика: прочее
фэнтези
5.00
рейтинг книги
Отмороженный 11.0

Надуй щеки! Том 7

Вишневский Сергей Викторович
7. Чеболь за партой
Фантастика:
попаданцы
дорама
5.00
рейтинг книги
Надуй щеки! Том 7

Идеальный мир для Лекаря 21

Сапфир Олег
21. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 21

Антимаг его величества. Том III

Петров Максим Николаевич
3. Модификант
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Антимаг его величества. Том III

Истребители. Трилогия

Поселягин Владимир Геннадьевич
Фантастика:
альтернативная история
7.30
рейтинг книги
Истребители. Трилогия