Рейтинговые книги
Читем онлайн C# 4.0: полное руководство - Герберт Шилдт

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 136 137 138 139 140 141 142 143 144 ... 294

    }

  }

}

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() необходимо указать его полное имя — NSl.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. Именно это и делает теперь программу пригодной для компиляции.

1 ... 136 137 138 139 140 141 142 143 144 ... 294
На этой странице вы можете бесплатно читать книгу C# 4.0: полное руководство - Герберт Шилдт бесплатно.
Похожие на C# 4.0: полное руководство - Герберт Шилдт книги

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