Полное руководство. С# 4.0 - Шилдт Герберт
Шрифт:
Интервал:
Закладка:
И в-третьих, ради наглядности примера рассматриваемая здесь программа быларазделена на два отдельных файла. В одном файле содержится код объявления пространства имен Counter, а в другом — код самой программы NSDemo. Но оба фрагмента кода можно было бы объединить в единый файл. Более того, в одном файле исходного кода может содержаться два или более пространства имен со своими собственными областями объявлений. Когда оканчивается действие внутреннего пространстваимен, возобновляется действие внешнего пространства имен — в примере с Counterэто глобальное пространство имен. Ради большей ясности в последующих примерахвсе пространства имен, требующиеся в программе, будут представлены в одном и томже файле. Следует, однако, иметь в виду, что их допускается распределять по отдельным файлам, что практикуется чаще в выходном коде.Предотвращение конфликтов имен с помощью пространств имен
Главное преимущество пространств имен заключается в том, что объявленные в нихимена не вступают в конфликт с именами, объявленными за их пределами. Например,в приведенной ниже программе определяются два пространства имен. Первым из нихявляется представленное ранее пространство имен Counter, а вторым — Counter2.Оба пространства имен содержат классы с одинаковым именем CountDown, но поскольку это разные пространства, то оба класса CountDown не вступают в конфликтдруг с другом. Кроме того, оба пространства имен определены в одном и том же файле. Как пояснялось выше, это вполне допустимо. Безусловно, каждое из этих пространств имен можно было бы выделить в отдельный файл, если бы в этом возниклапотребность.// Пространства имен предотвращают конфликты имен.using System;// Объявить пространство имен 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; } }}// Объявить пространство имен Counter2.namespace Counter2 { /* Этот класс CountDown относится к пространству имен Counter2 и поэтому не вступает в конфликт с аналогичным классом из пространства имен Counter. */ class CountDown { public void Count() { Console.WriteLine("Это метод Count() из " + "пространства имен Counter2."); } }}class NSDemo2 { static void Main() { // Это класс CountDown из пространства имен Counter. Counter.CountDown cd1 = new Counter.CountDown(10); // Это класс CountDown из пространства имен Counter2. Counter2.CountDown cd2 = new Counter2.CountDown(); int i; do { i = cd1.Count(); Console.Write(i + " "); } while(i > 0); Console.WriteLine(); cd2.Count(); }}
Вот к какому результату приводит выполнение этой программы.10 9 8 7 6 5 4 3 2 1 0Это метод Count() из пространства имен Counter2.
Как следует из приведенного выше результата, класс CountDown из пространстваимен Counter существует отдельно от класса того же названия из пространства именCounter2, и поэтому конфликт имен не возникает. Несмотря на всю простоту данногопримера, он наглядно показывает, как удается избежать конфликта имен в собственном коде и коде, написанном другими разработчиками, поместив классы с одинаковыми именами в разные пространства имен.Директива using
Если в программе присутствуют частые ссылки на члены конкретного пространстваимен, то указывать это пространство всякий раз, когда требуется ссылка на него, неочень удобно. Преодолеть это затруднение помогает директива using. В подавляющем большинстве приводившихся ранее примеров программ с помощью этой директивы делалось видимым глобальное для C# пространство имен System, поэтомуона отчасти вам уже знакома. Как и следовало ожидать, с помощью директивы usingможно сделать видимыми вновь создаваемые пространства имен.
Существуют две формы директивы using. Ниже приведена первая из них:using имя;
где имя обозначает имя того пространства имен, к которому требуется получить доступ. Все члены, определенные в указанном пространстве имен, становятся видимыми, и поэтому могут быть использованы без дополнительного определения их имен.Директиву using необходимо вводить в самом начале каждого файла исходного кодаперед любыми другими объявлениями или же в начале тела пространства имен.
Приведенная ниже программа является вариантом предыдущего примера, переработанным с целью продемонстрировать применение директивы using, делающейвидимым создаваемое пространство имен.// Продемонстрировать применение директивы using.using System;// Сделать видимым пространство имен Counter.using 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; } }}class NSDemo3 { static void Main() { // Теперь класс CountDown может быть использован непосредственно. CountDown cd1 = new CountDown(10); int i; do { i = cd1.Count(); Console.Write(i + " "); } while(i > 0); Console.WriteLine(); CountDown cd2 = new CountDown(20); do { i = cd2.Count(); Console.Write(i + " "); } while(i > 0); Console.WriteLine(); cd2.Reset(4); do { i = cd2.Count(); Console.Write(i + " "); } while(i > 0); Console.WriteLine(); }}
В эту версию программы внесены два существенных изменения. Первое из нихсостоит в применении директивы using в самом начале программы, как показанониже.using Counter;
Благодаря этому становится видимым пространство имен Counter. Второе изменение состоит в том, что класс CountDown больше не нужно дополнительно определять спомощью пространства имен Counter, как демонстрирует приведенная ниже строкакода из метода Main().CountDown cd1 = new CountDown(10);
Теперь пространство имен Counter становится видимым, и поэтому классCountDown может быть использован непосредственно.
Рассматриваемая здесь программа иллюстрирует еще одно важное обстоятельство:применение одного пространства имен не отменяет действие другого. Когда пространство имен делается видимым, это просто дает возможность использовать его содержимое без дополнительного определения имен. Следовательно, в данном примере обапространства имен, System и Counter, становятся видимыми.Вторая форма директивы using
Вторая форма директивы using позволяет определить еще одно имя (так называемый псевдоним) типа данных или пространства имен. Эта форма приведена ниже:using псевдоним = имя;
где псевдоним становится еще одним именем типа (например, типа класса) или пространства имен, обозначаемого как имя. После того как псевдоним будет создан, онможет быть использован вместо первоначального имени.
Ниже приведен вариант программы из предыдущего примера, измененный с целью показать создание и применение псевдонима MyCounter вместо составного имениCounter.CountDown.// Продемонстрировать применение псевдонима.using System;// Создать псевдоним для составного имени Counter.CountDown.using MyCounter = Counter.CountDown;// Объявить пространство имен для счетчиков.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; } }}class NSDemo4 { static void Main() { // Здесь и далее псевдоним MyCounter используется // вместо составного имени Counter.CountDown. MyCounter cd1 = new MyCounter(10); int i; do { i = cd1.Count(); Console.Write(i + " "); } while(i > 0); Console.WriteLine(); MyCounter cd2 = new MyCounter(20); do { i = cd2.Count(); Console.Write(i + " "); } while(i > 0); Console.WriteLine(); cd2.Reset(4); do { i = cd2.Count(); Console.Write(i + " "); } while(i > 0); Console.WriteLine(); }}
Псевдоним MyCounter создается с помощью следующего оператора.using MyCounter = Counter.CountDown;
После того как псевдоним будет определен в качестве другого имени классаCounter.CountDown, его можно использовать для объявления объектов без дополнительного определения имени данного класса. Например, в следующей строке кода израссматриваемой здесь программы создается объект класса CountDown.MyCounter cd1 = new MyCounter(10);Аддитивный характер пространств имен