
- •Оглавление
- •Об авторе
- •Посвящение
- •Благодарности
- •Ждем ваших отзывов!
- •Что такое .NET
- •Создание исходной программы
- •Тестовая поездка
- •Каркас программы
- •Комментарии
- •Введение в хитрости панели элементов
- •Повторное использование кода из панели элементов
- •Правила объявления переменных
- •Вариации на тему int
- •Объявление переменной с плавающей точкой
- •Ограничения переменных с плавающей точкой
- •Объявление переменных типа decimal
- •Сравнение десятичных и целых чисел, а также чисел с плавающей точкой
- •Логичен ли логический тип
- •Символьные типы
- •Что такое тип-значение
- •Неизменяемость строк
- •Основные операции над строками
- •Сравнение строк
- •Сравнение без учета регистра
- •Отличие строк в разных регистрах
- •Преобразование символов строки в символы верхнего или нижнего регистра
- •Поиск в строках
- •Как искать
- •Пуста ли строка
- •Удаление пробельных символов
- •Анализ числового ввода
- •Обработка последовательности чисел
- •Объединение массива строк в одну строку
- •Арифметика
- •Простейшие операторы
- •Порядок выполнения операторов
- •Оператор инкремента
- •Сравнение чисел с плавающей точкой
- •Составные логические операторы
- •Вычисление типа операции
- •Типы при присваивании
- •Перегрузка операторов
- •Ветвление с использованием if и switch
- •Инструкция if
- •Инструкция else
- •Как избежать else
- •Вложенные инструкции if
- •Конструкция switch
- •Циклы
- •Цикл без счетчика
- •Правила области видимости
- •Пример
- •Зачем нужны разные циклы
- •Зачем нужны массивы
- •Массив фиксированного размера
- •Массив переменного размера
- •Свойство Length
- •Инициализация массивов
- •Понятие <т>
- •Обобщенные коллекции
- •Инстанцирование пустого списка
- •Создание списка целых чисел
- •Преобразования списков в массивы и обратно
- •Подсчет количества элементов в списке
- •Поиск в списках
- •Инициализаторы массивов и коллекций
- •Выполнение специфичных для множеств задач
- •Создание множества
- •Добавление элемента в множество
- •Выполнение объединения
- •Пересечение множеств
- •Получение разности
- •Не используйте старые коллекции
- •Обход каталога файлов
- •Начало программы
- •Получение начальных входных данных
- •Создание списка файлов
- •Форматирование вывода
- •Вывод в шестнадцатеричном формате
- •Обход коллекций: итераторы
- •Доступ к коллекции: общая задача
- •Использование foreach
- •Формат индексатора
- •Блок итератора
- •Создание каркаса блока итератора
- •Итерирование дней в месяцах
- •Что же такое коллекция
- •Синтаксис итератора
- •Блоки итераторов произвольного вида и размера
- •Обобщенные классы безопасны
- •Обобщенные классы эффективны
- •Очередь с приоритетами
- •Распаковка пакета
- •Написание обобщенного кода
- •Использование простого необобщенного класса фабрики
- •Незавершенные дела
- •Ковариантность
- •Использование механизма исключений для сообщения об ошибках
- •Что происходит при генерации исключения
- •Исключительный пример
- •Что делает этот пример "исключительным"
- •Трассировка стека
- •Советы по написанию кода с хорошей обработкой ошибок
- •Анализ возможных исключений метода
- •Как выяснить, какие исключения генерируются теми или иными методами
- •Генерирующие исключения выражения
- •Работа с перечислениями
- •Создание перечислений с инициализаторами
- •Указание типа данных перечисления
- •Применение перечислений в конструкции switch
- •Процедурные поездки
- •Объектно-ориентированные поездки
- •Определение класса и объекта
- •Определение класса
- •Что такое объект
- •Различие между объектами
- •Работа со ссылками
- •Классы, содержащие классы
- •Определение константных членов-данных и членов-данных только для чтения
- •Передача аргументов методу
- •Передача методу нескольких аргументов
- •Соответствие определений аргументов их использованию
- •Перегрузка методов
- •Реализация аргументов по умолчанию
- •Возврат значения оператором return
- •Кортеж с двумя элементами
- •Создание кортежей более чем с двумя элементами
- •Глава 14 Поговорим об этом
- •Определение методов
- •Определение статического метода
- •Определение метода экземпляра
- •Полное имя метода
- •Ключевое слово this
- •Когда this используется явно
- •Что делать при отсутствии this
- •Использование локальных функций
- •Прочие уровни безопасности
- •Методы доступа
- •Пример управления доступом
- •Выводы
- •Статические свойства
- •Побочные действия свойств
- •Дайте компилятору написать свойства для вас
- •Методы и уровни доступа
- •Замена конструктора по умолчанию
- •Конструирование объектов
- •Непосредственная инициализация объекта
- •Конструирование с инициализаторами
- •Инициализация объекта без конструктора
- •Определение свойств с кодом
- •Определение конструкторов и деструкторов с кодом
- •Определение методов доступа к свойствам с кодом
- •Определение методов доступа к событиям с кодом
- •Наследование класса
- •Более сложный пример наследования
- •ЯВЛЯЕТСЯ или СОДЕРЖИТ
- •Доступ к BankAccount через содержание
- •Отношение СОДЕРЖИТ
- •Заменяемость классов
- •Неверное преобразование времени выполнения
- •Указание конкретного конструктора базового класса
- •Обновленный класс BankAccount
- •Перегрузка унаследованного метода
- •Простейший случай перегрузки метода
- •Различные классы, различные методы
- •Сокрытие метода базового класса
- •Вызов методов базового класса
- •Что неверно в стратегии использования объявленного типа
- •Использование is для полиморфного доступа к скрытому методу
- •Объявление метода виртуальным и перекрытие
- •Получение максимальной выгоды от полиморфизма
- •Разложение классов
- •Абстрактный класс: ничего, кроме идеи
- •Как использовать абстрактные классы
- •Создание абстрактных объектов невозможно
- •Опечатывание класса
- •Реализация интерфейса
- •Именование интерфейсов
- •Наследование и реализация интерфейса
- •Преимущества интерфейсов
- •Тип, возвращаемый методом
- •Что скрыто за интерфейсом
- •Гибкие зависимости через интерфейсы
- •Реализация отношения СОДЕРЖИТ с помощью интерфейсов
- •Определение делегата
- •Пример передачи кода
- •Делегирование задания
- •Очень простой первый пример
- •Более реальный пример
- •Создание приложения
- •Жизненный цикл делегата
- •Анонимные методы
- •Проектный шаблон Observer
- •Что такое событие. Публикация и подписка
- •Как издатель оповещает о своих событиях
- •Как подписаться на событие
- •Как опубликовать событие
- •Как наблюдатели "обрабатывают" событие
- •Сборки
- •Выполнимые файлы
- •Библиотеки классов
- •Создание проекта библиотеки классов
- •Создание автономной библиотеки классов
- •Создание классов для библиотеки
- •Использование тестового приложения
- •Дополнительные ключевые слова для управления доступом
- •protected: поделимся с подклассами
- •protected internal: более изощренная защита
- •Размещение классов в пространствах имен
- •Объявление пространств имен
- •Пространства имен и доступ
- •Использование полностью квалифицированных имен
- •Ссылочные типы
- •Выходные параметры
- •Альтернативные методы возврата значений
- •Работа с переменными out
- •Возврат значений по ссылке
- •Различия типов-значений
- •Когда следует использовать структуры
- •Добавление распространенных элементов структур
- •Управление отдельной записью
- •Добавление структур в массивы
- •Перекрытие методов
- •Определение того, что следует защищать
- •Документирование компонентов программы
- •Разложение компонентов на функции
- •Оценка рисков
- •Аутентификация с использованием входа в Windows
- •Безопасность развертывания
- •Уязвимости сценариев
- •Наилучшие методы защиты приложений Web Forms
- •Получение данных
- •Настройка образца схемы базы данных
- •Подключение к источнику данных
- •Работа с визуальными инструментами
- •Написание кода для работы с данными
- •Использование Entity Framework
- •Где водится рыба: файловые потоки
- •Потоки
- •Читатели и писатели
- •Пример использования потока
- •Как это работает
- •Наконец-то мы пишем!
- •Использование конструкции using
- •Загрузка файла из Интернета
- •Регистрация сетевой активности
- •Графика
- •Перья
- •Кисти
- •Текст
- •Классы рисования и каркас .NET
- •Приступая к работе
- •Настройка проекта
- •Обработка счета
- •Создание подключения к событию
- •Рисование доски
- •Запуск новой игры

на то, что приведенная демонстрационная программа не будет ком пилироваться - при такой попытке вы получите сообщение о том,
что обращение к члену DouЬleBankAccount . BankAccount . _balance
невозможно:
С шимго p((р |
й |
йгошимp((р й |
й 'шrшим(, т : :имш((, |
: , |
|
, |
, |
р: |
тхр |
,( :римr, ,r , |
|
Трудно сказать, зачем компилятор заставили выводить такие скучные сооб щения вместо короткого "не лезь к private", но суть именно в этом. Выраже ние Ьа . _balance += 1 0 ; оказывается некорректным именно по этой причине - в силу объявления _balance как private этот член недоступен методу Main ( ) , расположенному вне класса BankAccount. Замена данного выражения выра жением Ьа . Deposit ( 1 0 ) решает возникшую проблему - метод BankAccount . Deposit ( ) объявлен как puЫic, а потому доступен для метода Main ( ) .
Тип доступа по умолчанию - private, так что если вы забыли или сознательно пропустили модификатор для некоторого члена, это ана логично тому, как если бы вы описали его как private. Однако на
ЗАПОМНИ! стоятельно рекомендуется всегда использовать это ключевое слово явно во избежание любых недоразумений. Хороший программист всегда явно указывает свои намерения, что является еще одним ме тодом снижения количества возможных ошибок .
Прочие уровни безопасности
Вэтом разделе используются определенные знания о наследовании
ипространствах имен, которые будут рассмотрены в более поздних
главах книги (глава 16, "Наследование", и 20, "Пространства имен и ВНИМАНИВ библиотеки"). Вы можете пропустить этот раздел и вернуться к нему
позже, получив необходимые знания. Язык С# предоставляет следу ющие уровни безопасности.
>>Члены, объявленные как puЫ i c, доступны любому классу про граммы.
»Члены, объявленные как private, доступны только из текущего класса.
»Члены, объявленные как protected, доступны только из текущего класса и всех его подклассов.
»Члены, объявленные как internal, доступны для любого класса в
,том же модуле программы.
Модулем (module), или сборкой (assemЬly), в С# называется отдель но компилируемая часть кода, представляющая собой выполнимую
ГЛАВА 1 5 Класс: каждый сам за себя aоsи

. ЕХЕ-программу либо библиотеку . DLL. Одно пространство имен может распространяться на несколько модулей. (В главе 20, "Про странства имен и библиотеки'; рассматриваются сборки и простран ства имен С# и обсуждаются уровни доступа, отличные от puЫic и private.)
»Члены, объявленные как internal protected, доступны для теку щего класса и всех его подклассов, а также классов в том же модуле программы.
Сокрытие членов путем объявления их как private обеспечивает макси мальную степень безопасности. Однако зачастую такая высокая степень и не нужна. В конце концов, члены подклассов и так зависят от членов базового класса, так что ключевое слово protected предоставляет достаточно удобный уровень безопасности.
Зачем нужно управление. оступом
Объявление внутренних членов класса как puЫic - не лучшая мысль как минимум по следующим причинам.
»Объявляя члены-данные puЫic, вы не в состоянии просто определить, когда и как они модифицируются. Зачем беспоко
иться и создавать методы Deposit ( ) и Withdraw ( ) с проверками корректности? И вообще, зачем создавать любые методы, ведь лю бой метод любого класса может модифицировать данные счета в любой момент. Но если другой метод может обращаться к этим дан ным, то он практически обязательно это сделает.
Ваша программа BankAccount может проработать длительное вре мя, прежде чем вы заметите, что баланс одного из счетов отрицате лен. Метод Withdraw ( ) призван оградить от подобной ситуации, но в описанном случае непосредственный доступ к балансу, минуя ме тод Withdraw ( ) , имеют и другие методы. Вычислить, какие именно методы и при каких условиях поступают так некорректно, - задача не из легких.
»Доступ ко всем членам-данным класса делает его интерфейс слишком сложным. Как программист, использующий класс Bank
Account, вы не хотите знать о том, что делается внутри него. Вам до статочно знаний о том, как положить деньги на счет и снять их с него.
)) Доступ ко всем членам-данным класса приводит к "растека нию" правил класса. Например, класс BankAccount не позво ляет балансу стать отрицательным ни при каких условиях. Это -
328 ЧАСТЬ 2 Объектно-ориентирован ное программирование на С#

бизнес-правило, которое должно быть локализовано в методе Withdraw ( ) . В противном случае вам придется добавлять соответ ствующую проверку в весь код, в котором осуществляется измене ние баланса.
|
Что произойдет, если банк решит изменить правила и часть клиен |
|
тов с хорошей кредитной историей получит право на небольшой |
|
отрицательный баланс в течение короткого времени? Вам придется |
|
долго рыскать по всей программе и вносить изменения во все ме |
|
ста, где выполняется непосредственное обращение к балансу. |
|
tу дукиkвуакиллп е нуводп зокуу долвблрпне. )ун rво руозeодее |
|
нооювору иисироедикЬрия зояор0 eиаусомч rво лсолво лонойув |
|
мин лреоевЬаокенулвмооаезоа маодуtбо моонойролвееллокЬобkву |
СОВЕТ |
нодемеаивос private, и оивунисе руозeоденолве лодрениkву уродо |
|
protected, internal, internal protected И Л И puЫic. |
Методы доступа
ь-. C -0 2!.00 -)C-(,0. |
)! .!--!,,C,0 |
)( |
<.(-- BankAccount, во бмедее |
|
||||
ву рулаокЬаодсбреe нуводомеддер ео реeц GetString ( ) , моомси.иув лвсо( |
|
|||||||
аомбт муслет |
лнуви дкя мпмоди уу ри rасир иолсудлвмонмпоомиConsole . |
|
||||||
WriteLine ( ) . Cуко мвонД)во мпмодлодусйеноh озеуави BankAccount нойуь |
|
|||||||
зпв0 оивсбдрурДулке rволодусйеноу рудолвбирояо вонб йуцлкудбялсеррелб |
|
|||||||
aовдиkвуаулирт аулисумо<.акиллдо уренув0 лсимолин суаив0. тиа ор збдув |
|
|||||||
лсудлвимкур лсе мпмодуt |
|
|
|
|
|
|
||
ос ону вороценуувля дминуводи дкя pгщiинжСP ежПинжСP GetBalance ( ) е |
|
|||||||
GetAccountNumЬer ( ) , е нувод i2оПжгжыС ежПинжаP - SetAccountNumЬer ( ) . |
|
|||||||
хп нойуву бдемев0лягои)ун виа мокромив0ляеохоивороц)во )к ур balance |
|
|||||||
збдув озеямкур аиа private, е лсе rвон лсудолвимкяв0нувод GetBalance ( ) ? |
|
|||||||
dи линон дуку дкя rво |
енутвля. |
долвивонромулаеу олромиреяC |
|
|
||||
» |
ччиth-hlРч. |
|
Ч.не дает возможности изменять член |
ц ц |
д |
|||
|
он только возвращает его значение. Тем самым значение баланса |
|
||||||
|
делается доступным только для чтения. Используя аналогию с на |
|
||||||
|
стоящим банком, вы можете просмотреть состояние своего счета в |
|
||||||
|
любой момент, но не можете снять с него деньги иначе, чем с приме |
|
||||||
» |
нением процедур, |
предусмотренных для этого банком. |
|
|
||||
Метод д |
ц |
ц скрываетд |
внутренний формат класса от |
|
||||
|
внешних методов. Метод GetBalance ( ) может в процессе работы |
|
||||||
|
выполнять некоторые вычисления, обращаться к базе данных бан |
|
||||||
|
ка - словом, выполнять какие-то действия, чтобы получить состо |
|
||||||
|
яние счета. Внешние методы ничего об этом не знают и не должны |
|
||||||
|
знать. Продолжая аналогию, вы интересуетесь состоянием счета, но |
|
||||||
|
не знаете, |
как, где и в каком именно виде хранятся ваши деньги. |
|
ГЛАВА 1 5 Класс: каждый сам за себя иоС.

Пример управления доступом
|
Д.......... |
|
..3.. |
......... |
...... |
...1..... |
|
|
|
...7.g |
.... |
.....4.....L. |
|
.. |
|
.L ... |
..... |
......1. |
|
....... |
.. .. |
.. ..... |
щ |
.7. |
.. |
П.... |
.........5.. |
......... |
..... |
...1..... |
|
Ф
Ф |
|
|
Ф . |
|
. |
. |
Ф |
. |
Ф |
|
|
|
|
|
Ф . |
|
. |
Ф |
|
|
Ф . |
. |
Ф |
Ф. |
|
. |
Ф |
|
|
Ф . |
Ф |
. |
|
|
|
б . |
|
. |
. |
|
. |
Ф |
|
|
ЧАСТЬ 2 рeеtиосор оерtсореi.,ссioi oеiде,яя реi. ,срoi эЬ С#

Метод знбла рсоздает банковский счет и вносит на него сумму 1 23,454, т.е. сумму с дробным количеством копеек. Затем метод знела рвносит на счет еще одну долю копейки и выводит баланс счета. Вывод программы выглядит сле дующим образом:
ыИ
ен а |
ы И |
ыД
ен а |
ы И |
Г И Д
Пользователь начинает жаловаться на некорректные расчеты. Похоже, в программе имеется ошибка.
Проблема, конечно, в том, что 5аш и5l5 выводится как 5аш75lшЧтобы избе жать проблем, банк принимает решение округлять вклады и снятия до ближай шей копейки. Простейший путь осуществить Клаф, конвертировать счета в аопетнви использовать метод попбтнСшоомлаа 2какн Клафсделано в демонстра ционной программе попетнвбнлИппомлАш
|
1 |
ог
И
ен
И
ен
Д
гк
И
Д
Дк
к т |
|
т 5 |
|
т |
|
т г |
|
о г |
|
к з |
|
|
|
|
|
Д |
|
|
|
щ т |
|
т , |
г |
г |
|
|
|
к т |
ен |
о шД |
о г |
ко |
|
И |
|
|
о у |
г |
|
|
|
г |
|
ГЛАВА 1 5 Класс: каждый сам за себя |
1 |
33 |


ГЛАВА 1 5 Класс: каждый сам за себя бббt