Читать интересную книгу "Полное руководство. С# 4.0 - Шилдт Герберт"

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 107 108 109 110 111 112 113 114 115 ... 188

Под одним именем можно объявить несколько пространств имен. Это дает возможность распределить пространство имен по нескольким файлам или даже разделить его в пределах одного и того же файла исходного кода. Например, в приведеннойниже программе два пространства имен определяются под одним и тем же именемCounter. Одно из них содержит класс CountDown, а другое — класс CountUp. Во время компиляции содержимое обоих пространств имен Counter складывается.// Аддитивный характер пространств имен.using System;// Сделать видимым пространство имен Counter.using Counter;// Это одно пространство имен Counter.namespace Counter { // Простой вычитающий счетчик. class CountDown { int val; public CountDown(int n) { val = n; } public void Reset(int n) { val = n; } public int Count() { if(val > 0) return val--; else return 0; } }}// А это другое пространство имен Counter.namespace Counter { // Простой суммирующий счетчик. class CountUp { int val; int target; public int Target { get{ return target; } } public CountUp(int n) { target = n; va1 = 0; } public void Reset(int n) { target = n; val = 0; } public int Count() { if(val < target) return val++; else return target; } }}class NSDemo5 { static void Main() { CountDown cd = new CountDown(10); CountUp cu = new CountUp(8); int i; do { i = cd.Count(); Console.Write(i + " "); } while(i > 0); Console.WriteLine(); do { i = cu.Count(); Console.Write(i + " "); } while(d < cu.Target); }}

Вот к какому результату приводит выполнение этой программы.10 9 8 7 6 5 4 3 2 1 00 1 2 3 4 5 6 7 8

Обратите также внимание на то, что директиваusing Counter;

делает видимым все содержимое пространства имен Counter. Это дает возможностьобращаться к классам CountDown и CountUp непосредственно, т.е. без дополнительного указания пространства имен. При этом разделение пространства имен Counter надве части не имеет никакого значения.Вложенные пространства имен

Одно пространство имен может быть вложено в другое. В качестве примера рассмотрим следующую программу.// Вложенные пространства имен.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); // ... }}

1 ... 107 108 109 110 111 112 113 114 115 ... 188
Прочитали эту книгу? Оставьте комментарий - нам важно ваше мнение! Поделитесь впечатлениями и помогите другим читателям сделать выбор.
Книги, аналогичгные "Полное руководство. С# 4.0 - Шилдт Герберт"

Оставить комментарий