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

на главную

Жанры

Полное руководство. С# 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); // ... } }

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

Без шансов

Семенов Павел
2. Пробуждение Системы
Фантастика:
боевая фантастика
рпг
постапокалипсис
5.00
рейтинг книги
Без шансов

Неудержимый. Книга XVII

Боярский Андрей
17. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга XVII

Дворянская кровь

Седой Василий
1. Дворянская кровь
Фантастика:
попаданцы
альтернативная история
7.00
рейтинг книги
Дворянская кровь

Шатун. Лесной гамбит

Трофимов Ерофей
2. Шатун
Фантастика:
боевая фантастика
7.43
рейтинг книги
Шатун. Лесной гамбит

Лорд Системы 14

Токсик Саша
14. Лорд Системы
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Лорд Системы 14

Романов. Том 1 и Том 2

Кощеев Владимир
1. Романов
Фантастика:
фэнтези
попаданцы
альтернативная история
5.25
рейтинг книги
Романов. Том 1 и Том 2

Законы Рода. Том 5

Flow Ascold
5. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 5

Матабар

Клеванский Кирилл Сергеевич
1. Матабар
Фантастика:
фэнтези
5.00
рейтинг книги
Матабар

Ученик. Второй пояс

Игнатов Михаил Павлович
9. Путь
Фантастика:
фэнтези
боевая фантастика
5.67
рейтинг книги
Ученик. Второй пояс

Кодекс Охотника. Книга ХХ

Винокуров Юрий
20. Кодекс Охотника
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга ХХ

Бездомыш. Предземье

Рымин Андрей Олегович
3. К Вершине
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Бездомыш. Предземье

Чехов. Книга 2

Гоблин (MeXXanik)
2. Адвокат Чехов
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Чехов. Книга 2

Ваше Сиятельство 3

Моури Эрли
3. Ваше Сиятельство
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Ваше Сиятельство 3

Я снова не князь! Книга XVII

Дрейк Сириус
17. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я снова не князь! Книга XVII