ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 11.12.2025

Просмотров: 3194

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

В нормальных условиях метод

Inverse () возвращает корректное значение. При

передаче ему нуля он генерирует

исключение CustomException, передавая ему стро­

ку пояснения вместе с вызвавшим

исключение объектом.

Функция Main () перехватывает исключение и выводит короткое сообщение, поясняющее суть происшедшего. "Неизвестная фатальная ошибка", вероятно, означает, та программа "закрывает лавочку и уходит на отдых". Но функция Main () дает исключе­ нию шанс пояснить, что же все-таки произошло, вызывая его метод ToString ().

Визитка класса: метод ToString ()

Все классы наследуют один общий базовый класс с именем Object. Об этом уже го­ ворилось в главе 14, "Интерфейсы и структуры". Здесь, однако, стоит упомянуть о ме­ тоде ToString () в составе этого класса. Метод предназначен для преобразования содержимого класса в строку. Идея заключается в том, что каждый класс должен пе­ рекрывать метод ToString ( ) , чтобы осуществить вывод значащей информации. В первых главах был использован метод GetString ( ) , чтобы не касаться в них во­ проса наследования; однако принцип остается тем же. Например, корректный метод Student. ToString () может выводить имя и идентификатор студента.

Большинство функций — даже встроенных в библиотеку С # — применяют метод ToString () для вывода объектов. Таким образом, перекрытие ToString () имеет очень полезное побочное действие, заключающееся в том, что каждый объект выво­ дится в своем собственном формате, безотносительно к тому, кем именно он выведен.

Поскольку объект исключения в этом случае на самом деле принадлежит типу Cus­ tomException, управление передается CustomException. ToString ().

Метод Message () представляет собой виртуальный метод класса Excep­ tion, так что его можно перекрывать, но пользовательское исключение долж­ но наследовать его без перекрытия.

Метод Message О позволяет объекту MathClass выводить информацию о самом себе с использованием метода ToString ( ) . Метод MathClass.ToString() воз­ вращает строку, в которой содержится описание и значение объекта.

Не следует брать на себя больше того, что имеете. Используйте метод объекта ToString () для создания строковой версии объекта, не пытаясь влезть в сам объект и получить его значения. В общем случае нужно полагаться на откры­ тый интерфейс — открытые члены, — а не на знания о внутреннем устройстве объекта. Оно инкапсулировано (по крайней мере должно быть инкапсулирова­ но) и может измениться в новых версиях.

Вывод демонстрационной программы CustomException имеет следующий вид:

Неизвестная фатальная ошибка:

Сообщение <Нельзя делить на 0>, Объект (Value = 0) CustomException.MathClass

Исключение сгенерировано в Double Inverse() Нажмите <Enter> для завершения программы...

416

Часть VII. Дополнительные глава


И последнее: сообщение "Неизвестная фатальная ошибка:" поступает от

Main ( ) . Строка "Сообщение <Нельзя делить на 0>, Объект <~~>" посту­ пает от CustomException. Часть Value = 0 предоставляет объект MathClass. Последняя строка, Исключение сгенерировано в Double Inverse ( ) , при­ надлежит CustomException. Это нельзя назвать иначе, как исключительным со­ трудничеством.

Глава 18. Эти исключительные исключения

417

Глава 19

Работа с файлами и библиотеками

>Работа с несколькими исходными файлами в одной программе У Сборки и пространства имен

>Библиотеки классов

>Чтение и запись файлов данных

оступ к файлам в С# может иметь два различных значения. Наиболее очевид­ ное — это хранение и считывание данных с диска. О том, как осуществляется ввод-вывод данных с диска, вы узнаете из этой главы. Второе значение связано

с тем, каким образом исходный текст С# группируется в исходные файлы.

Функции позволяют разделить длинную строку исходного текста на отдельные моду­ ли, которые можно легче сопровождать и поддерживать. Классы дают возможность группировать данные и функции для дальнейшего снижения сложности программы — программы достаточно сложны, а людям свойственно ошибаться, так что нужно пользо­ ваться любой возможностью упрощения, которая может помочь избежать ошибок.

С# обеспечивает еще один уровень группировки: он позволяет сгруппировать подоб­ ные классы в отдельную библиотеку. Помимо написания собственных библиотек, вы можете использовать в ваших программах и чужие библиотеки. Такие программы со­ держат множество модулей, называемых сборками (assemblies). О них также будет рас­ сказано в данной главе. Кроме того, описанное в главе 11, "Классы", управление досту­ пом на самом деле несколько сложнее в связи с применением пространств имен — еще одного способа группирования похожих классов, которое заодно позволяет избежать дублирования имен в двух частях программы. В этой главе речь пойдет и о них.

Программы в настоящей книге носят исключительно демонстрационный характер. Ка­ ждая из них длиной не более нескольких десятков строк и содержит не более пары классов. Программы же промышленного уровня со всеми "рюшечками" и "финтифлюшечками" мо­ гут состоять из сотен тысяч строк кода с сотнями классов.

Рассмотрим систему продажи авиабилетов. У вас должен быть один интерфейс для заказа билетов по телефону, другой — для тех, кто заказывает билет по Интернету, должна быть часть программы, отвечающая за управление базой данных билетов, дабы не продавать один и тот же билет несколько раз, еще одна часть должна следить за стой-


мостью билетов с учетом всех налогов и скидок, и так далее и тому подобное... Такая программа будет иметь огромный размер.

Размещение всех составляющих программу классов в одном исходном файле Pro­ gram, с s быстро становится непрактичным. Оно даже более неприемлемо, чем разде имущества, которого добилась моя бывшая жена, по следующим причинам.

У вас возникнут проблемы при поддержке классов. Единый исходный фа очень трудно поддается пониманию. Гораздо проще разбить его на отдельные мо­ дули, например ResAgentlnterf асе . cs, GateAgentlnterf асе . cs, Res-j

Agent.cs, GateAgent.cs, Fare.cs и Aircraft.cs.

Работа над большими программами обычно ведется группами программи­ стов. Два программиста не в состоянии редактировать одновременно один и та же файл — каждому требуется его собственный исходный файл (или файлы).; У вас может быть 20 или 30 программистов, одновременно работающих над од­ ним большим проектом. Один файл ограничит работу каждого из 24 программи­ стов над проектом всего одним часом в сутки, но стоит разбить программу на 24 файла, как становится возможным (хотя и сложным) заставить всех программи­ стов трудиться круглые сутки. Разбейте программу так, чтобы каждый класс со­ держался в отдельном файле, и ваша группа заработает как слаженный оркестр.

Компиляция больших файлов занимает слишком много времени. В результа­ те босс начнет нервничать и выяснять, почему это вы так долго пьете кофе вместо того, чтобы стучать по клавишам?

Какой смысл перестраивать всю программу, когда кто-то из программистов изме­ нил пару строк кода? Visual Studio 2005 может перекомпилировать только изме­ ненный файл и собрать программу из уже готовых объектных файлов.

По всем этим причинам программисты на С# предпочитают разделять программу на отдельные исходные файлы . CS, которые компилируются и собираются вместе в единый выполнимый . ЕХЕ-файл.

Файл проекта содержит инструкции о том, какие файлы входят в проект и как они должны быть скомбинированы друг с другом.

Можно объединить файлы проектов для генерации комбинаций программ, которые зависят от одних и тех же пользовательских классов. Например, вы можете захотеть объ­ единить программу записи с соответствующей программой чтения. Тогда, если изменя­ ется одна из них, вторая перестраивается автоматически. Один проект может описывать программу записи, второй — программу чтения. Набор файлов проектов известен под

названием решение

(solution). (Далее в главе будут рассматриваться две такие програм­

м ы — FileRead и

FileWrite, которые можно было бы объединить в одно решение,

но это так и не было сделано.)

Программисты на Visual С# используют Visual Studio Solution Explorer для объ­ единения нескольких исходных файлов С# в проекты в среде Visual Studio 2005. Solution Explorer будет описан в главе 21, "Использование интерфейса Visual Studio".

420

Часть VII. Дополнительные главы


В Visual Studio, а также в C#, Visual Basic .NET и прочих языках .NET один проект соответствует одному скомпилированному модулю — в .NET он носит имя сборка.

С# может создавать два основных типа сборок — выполнимые файлы (с расширени­ ем .ЕХЕ) и библиотеки классов (.DLL). Выполнимые файлы представляют собой про­ граммы сами по себе и используют код поддержки из библиотек. Во всей этой книге созда­ вались исключительно выполнимые файлы. Что касается библиотек классов, то опять же все программы в книге их используют. Например, пространство имен System— место размещения таких классов, как String, Console, Exception, Math и Object— су­ ществует как набор библиотечных сборок. Каждой программе требуются классы System.

Библиотеки не являются самостоятельными выполнимыми программами.

Библиотека классов состоит из одного или нескольких классов, обычно работающих вместе тем или иным способом. Зачастую классы в библиотеках находятся в своем соб­ ственном пространстве имен (namespace). (О них речь пойдет в следующем разделе.) Вы можете построить библиотеку математических подпрограмм, библиотеку для работы со строками, библиотеку классов-фабрик и т.д.

Небольшие программы обычно состоят из одной сборки programName.ехе. Одна­ ко часто создаются решения, состоящие из нескольких отдельных (но связанных) проек­ тов, как упоминалось в предыдущем разделе. Каждый из них компилируется в отдельную сборку. В решении вы можете объединять и . ЕХЕ-, и . DLL-файлы, что является обычной практикой ДЛЯ больших программ. Когда ВЫ строите многопроектное решение, сборки работают совместно, обеспечивая функциональность приложения в целом.

Если решение содержит более одного . ЕХЕ-проекта, вы должны указать Visual Studio, какой проект является начальным (startup project). Именно он будет запус­ каться при выборе команды меню Debug^Start Debugging (F5) or Debugs Start Without Debugging (<Ctrl+F5>). Для указания начального проекта щелкни­ те на нем правой кнопкой мыши в окне Solution Explorer и выберите в раскры­ вающемся меню команду Set as Startup Project. Имя начального проекта в окне Solution Explorer выделяется полужирным шрифтом. О Solution Explorer речь пойдет в главе 21, "Использование интерфейса Visual Studio".

Большие программы обычно разделяют свои компоненты на один выполнимый файл и несколько библиотек. Например, весь код, связанный с заказом билетов в рассматривав­ шемся ранее приложении, может находиться в одной библиотеке, работа с Интернетом — в другой, а управление базами данных — в третьей. Когда такая программа устанавливает­ ся на компьютер пользователя, процесс инсталляции включает копирование ряда файлов в соответствующие места на диске компьютера, причем многие из них являются .DLL- файлами, или просто "DLL" на сленге программистов (DLL означает dynamic link library (динамически компонуемые библиотеки) — код, который загружается в память тогда, ко­ гда в нем возникает необходимость при запуске используемой программы).

taa 19. Работа с файлами и библиотеками

421


Иногда бывает так, что все решение представляет собой не что иное, как библиотек классов, а не выполняемую программу. (Обычно при разработке такой библиотеки соз дается также сопутствующий . ЕХЕ-проект, именуемый драйвером, который предназна­ чен для тестирования библиотеки в процессе разработки. Однако при выпуске готовой

библиотеки для других программистов вы поставляете им только . DLL, но не

. ЕХЕ

а также, надеюсь, документацию к этим классам!)

 

Как создавать собственные библиотеки классов, будет рассказано немного

позже

в этой главе.

 

Пространства имен существуют для того, чтобы можно было поместить связанны классы в "одну корзину", и для снижения коллизий между именами, используемые в разных местах. Например, вы можете собрать все классы, связанные с математически­ ми вычислениям, в одно пространство имен MathRoutines.

Можно (но вряд ли будет сделано на практике) разделить на несколько пространств имен один исходный файл. Гораздо более распространена ситуация, когда несколько файлов группируются в одно пространство имен. Например, файл Point.cs может со= держать класс Point, а файл ThreeDSpace.cs— класс ThreeDSpace, описываю­ щий свойства Евклидова пространства. Вы можете объединить Point.cs, ThreeD­ Space . cs и другие исходные файлы С# в пространство имен MathRoutines (и, веро­ ятно, в библиотечную сборку MathRoutines). Каждый файл будет помещать свой код в одно и то же пространство имен. (В действительности пространство имен составляют классы в этих исходных файлах, а не файлы сами по себе.)

Пространства имен служат для следующих целей.

Пространства имен помещают груши к грушам, а не к яблокам. Как при кладной программист, вы можете не без оснований предполагать, что все классы, составляющие пространство имен MathRoutines, имеют отношение к математи­ ческим вычислениям. Так что поиск некоторой математической функции следует начать с просмотра классов, составляющих пространство имен MathRoutines.

Пространства имен позволяют избежать конфликта имен. Например, библио тека для работы с файлами может содержать класс Convert, который преобразу­ ет представление файла одного типа к другому. В то же время библиотека перево­ да может содержать класс с точно таким же именем. Назначая этим двум множе­ ствам классов пространства имен FilelO и TranslationLibrary, вы устраняете проблему: класс FilelO. Convert, очевидно, отличается от класса

TranslationLibrary.Convert.

Объявление пространств имен

Пространства имен объявляются с использованием ключевого слова namespace, за которым следует имя и блок в фигурных скобках. Классы в этом блоке являются частью пространства имён,

namespace MyStuff

{

422

Часть VII. Дополнительные главы