1629295403-b876e2087bddebea4bc9666fb2377a02 (846199), страница 83
Текст из файла (страница 83)
Но можно сделать массы и методы из пространства имен NamespaceB видимыми для пространства именNamespaceA. Обращаться вы можете только к тому, что видимо для вас.Видимы ли вам необходимые классы и методы?Для того чтобы определить, может ли класс Classl в пространстве имен NamespaceAвызывать NamespaceB. Class2 . AMethod ( ) , рассмотрим следующие два элемента.1. Видим ли класс Class2 из пространства имен NamespaceB вызывающемуклассу Classl? Это вопрос видимости пространства имен, который будет вскорерассмотрен.2. Если ответ на первый вопрос — "да", то "достаточно ли открыты" Class2 и егометод AMethod () классу Classl для доступа? "Достаточная открытость" определяется как наличие спецификаторов доступа нужной степени строгости с точкизрения вызывающего класса Classl.
Это вопрос управления доступом, рассматривающийся в главе 11, "Классы".Если Class2 находится в сборке, отличной от сборки Classl, он должен бытьоткрыт (publ ic) для Classl для доступа к его членам. Если же это одна и та жесборка, Class2 должен быть объявлен как минимум как internal. Классы могут быть только public, protected, internal или private.Аналогично, методуровень доступа вinternal в списокзывается в главе 11,класса Class2 должен иметь как минимум определенныйкаждой из этих ситуаций. Методы добавляют protectedспецификаторов доступа класса.
Детальнее об этом расска"Классы".Вы должны получить ответ "да" на оба поставленных вопроса, чтобы класс Classlмог вызывать методы Class2.Остальной приведенный здесь материал посвящен вопросам использования и видимости пространств имен.Как сделать видимыми классы и методы в другом пространстве именС# предоставляет два пути сделать элементы в пространстве имен NamespaceB видимыми в пространстве имен NamespaceA.424Насть VII.
Дополнительные главыПрименяя полностью квалифицированные имена из пространства имен NamespaceB при использовании их в пространстве имен NamespaceA. Это приводитк коду наподобие приведенного, начинающемуся с имени пространства имен,к которому добавляется имя класса и имя метода:System.Console.WriteLine("my s t r i n g " ) ;Устраняя необходимость в полностью квалифицированных именах в пространствеименNamespaceAпосредствомдирективыusingдляпространстваименNamespaceB:using NamespaceB;Программы в этой книге используют последний способ — директиву using. Полностью квалифицированные имена и директивы using будут рассмотрены в двух следующих разделах.Доступ к классам с использованием полностьюквалифицированных именПространство имен класса является составной частью его расширенного имени, чтоприводит к первому способу обеспечения видимости класса из одного пространстваимен в другом.
Рассмотрим следующий пример, в котором не имеется ни одной директивы using для упрощения обращения к классам в других пространствах имен:namespace MathRoutines{class Sort{public void SomeFunction(){}namespacePaint{public class{PaintColorpublic PaintColor(int nRed, int nGreen,public void Paint() {}public static- void StaticPaint () {}int nBlue){}}namespace MathRoutines{public class Test{static public void Main(string[]args)// Создание объекта типа Sort из того же пространства// имен, в котором мы находимся, и вызов некоторой// функцииSort obj = new S o r t ( ) ;obj.SomeFunction();// Создание объекта в другом пространстве имен —// обратите внимание, что пространство имен должно// быть явно включено в каждую ссылку на классГлава 19. Работа с файлами и библиотеками425Paint.PaintColor black = new Paint.PaintColor(0, 0, 0);black.Paint();Paint.PaintColor.StaticPaint();}}В этом случае классы Sort и Test содержатся внутри одного и того же пространства имен MathRoutines, хотя и объявляются в разных местах файла.
Это пространствоимен разбито на две части (в данном случае в одном и том же файле).В обычной ситуации Sort и Test оказались бы в различных исходных файлахС#, которые вы бы собрали в одну программу.Функция Test. Main () может обращаться к классу Sort без указания его пространства имен, так как оба эти класса находятся в одном и том же пространстве имен,Однако Main () должна указывать пространство имен Paint при обращении кPaintColor, как это сделано в вызове Paint, PaintColor. StaticPaint ( ) .
Здесьиспользовано полностью квалифицированное имя.Обратите внимание, что вам не требуется принимать специальных мер при обращении к black. Paint ( ) , поскольку класс и пространство имен объекта black известныДиректива usingОбращение к классу с использованием полностью квалифицированного имени быстро становится раздражающим. С# позволяет избежать излишнего раздражения с помощ ь ю ключевого слова using. Директива using добавляет указанное пространство именв список пространств имен по умолчанию, в которых С# выполняет поиск при разрешении имени класса.
Следующий пример компилируется без каких-либо замечаний:namespace Paint{public class PaintColor{public PaintColor(int nRed, int nGreen, int nBlue)public void Paint() {}public static void StaticPaint() {}{}namespace MathRoutines{// Добавляем Paint к пространствам имен, в которых// выполняется автоматический поискusing Paint;public class Test{static public void Main(string[] args){// Создаем объект в другом пространстве имен —// название пространства имен не требуется включать в// имя, поскольку само пространство имен было включено// полностью с использованием директивы "using"PaintColor black = new PaintColor(0, 0, 0 ) ;426Часть VII. Дополнительные главыblack.Paint();PaintColor.StaticPaint();Директива using говорит компилятору: "Если ты не в состоянии найти определенный класс в текущем пространстве имен, посмотри еще и в этом пространстве имен, может, ты найдешь его там".
Можно указать любое количество пространств имен, но всеони должны быть указаны в самом начале программы (либо внутри, либо снаружи блокапространства имен), как описано ранее в разделе "Объявление пространств имен".Все программы включают директиву using System,-. Эта команда даетпрограмме автоматический доступ к функциям, включенным в системнуюбиблиотеку, таким как WriteLine ().Использование полностью квалифицированных именПриведенная далее демонстрационная программа NamespaceUse иллюстрирует влияние пространств имен на видимость и использование директивыusing и полностью квалифицированных имен, чтобы обеспечить видимость элемента.// NamespaceUse - демонстрирует доступ к объектам с одним и// тем же именем в разных пространствах именusing System; // Все пространства имен нуждаются в этой// директиве для доступа к классам типа String// и Consolenamespace MainCode{using LibraryCodel; // Эта директива упрощает MainCodepublic class Classl{public void AMethod(){Console.WriteLine("MainCode.Classl.AMethod() ") ;}// Функция M a i n ( ) :static void Main(string[] args)// Создание экземпляра класса, содержащего функцию// Main, в данном пространстве именClassl cl = new C l a s s l О ; // MainCode.Classlcl.AMethod();// Никогда не вызывайте// Main() самостоятельно!// Создание экземпляра LibraryCodel.Classl// Приведенный далее код создает объект// MainCode.Classl, а не тот, что вы хотели, так как// нет ни директивы using, ни полностью// квалифицированного имениClassl с2 = new Classl(),•с2.AMethod();// Однако полностью квалифицированное имя создает// объект требуемого класса.
Имя следуетГлава 19. Работа с файлами и библиотеками427// квалифицировать даже при использовании директивы// using, поскольку оба пространства имен содержат// класс ClasslLibraryCodel.Classl сЗ = new LibraryCodel.Classl();c3 .AMethod () ,// В то же время создание LibraryCodel.Class2 не// требует полностью квалифицированного имени,// поскольку имеется директива using при отсутствии// коллизии имен; С# может без труда найти Class2Class2 с4 = new C l a s s 2 ( ) ;с4.AMethod();// Создание экземпляра LibraryCode2.Classl требует// полностью квалифицированного имени, как из-за// отсутствия директивы using для LibraryCode2, так и// потому, что оба пространства имен имеют Classl// Примечание: этот способ работает даже несмотря на// то, что LibraryCode2.Classl объявлен как internal,// а не public, поскольку оба класса находятся в одной// компилируемой сборкеLibraryCode2.Classl с5 = new LibraryCode2.Classl();с5.AMethod();// Ожидаем подтверждения пользователяConsole.WriteLine("Нажмите <Enter> для " +"завершения программы...");Console.Read();}namespace LibraryCodel{public class Classl// Имя дублирует Classl в другом{// пространстве именpublic void AMethod() // Имя дублировано в другом{// пространстве именConsole.WriteLine("LibraryCodel.Classl.AMethod()");}}public class Class2// Имя уникально, его нет в другом{// пространстве именpublic void AMethod(){Console.WriteLine("LibraryCodel.Class2.AMethod()");namespace LibraryCode2{class Classl{public void AMethod(){// Нет ключевых слов, описывающих// доступ: по умолчанию доступ —// internalConsole.WriteLine("LibraryCode2.Classl.AMethod()");}428Часть VII.
Дополнительные главыДанная демонстрационная программа включает три пространства имен: MainCode,в которое входит один класс Classl, содержащий функцию Main() и один дополнительный метод AMethod ( ) . Пространство имен LibraryCodel содержит два класса:Classl дублирует имя Classl из пространства имен MainCode, класс Class2 уникален. Пространство имен LibraryCode2 имеет один класс, также названный Classl,имя которого создавало бы коллизию с именем Classl в другом пространстве имен, если бы эти имена не были разделены и размещены каждое в своем пространстве имен.Каждый их этих классов имеет метод AMethod ().Функция Main () из MainCode .
Classl пытается создать и использовать MainCode. Classl (класс-владелец M a i n O ) , LibraryCodel. Classl, LibraryCodel .Class2 и LibraryCode2 .Classl. После создания объектов функция вызывает метод AMethod () каждого из них. Каждый метод идентифицирует свое местоположение. Вывод демонстрационной программы на экран выглядит следующим образом:MainCode.Classl.AMethod()MainCode.Classl.AMethod()LibraryCodel.Classl.AMethod()LibraryCodel.Class2.AMethod()LibraryCode2.Classl.AMethod()Нажмите <Enter> для завершенияпрограммы...Без разделения на различные пространства имен компилятор не может позволитьдублирования имен классов в M a i n O .
При применении пространств имен исходныйтекст компилируется, но вы должны использовать либо директиву using, либо полностью квалифицированные имена для обращения к объектам в разных пространствахимен. Пространство имен MainCode содержит директиву using для пространства именLibraryCodel, так что функция M a i n O из MainCode.