
- •Оглавление
- •Об авторе
- •Посвящение
- •Благодарности
- •Ждем ваших отзывов!
- •Что такое .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
- •Приступая к работе
- •Настройка проекта
- •Обработка счета
- •Создание подключения к событию
- •Рисование доски
- •Запуск новой игры

static void Main (string [ ] args)
{
// Создание объекта DoMath DoMath rnath = new DoMath ( ) ;
// Тестирование функций |
2 |
DoMath |
|
2 ) ) ; |
|
Console . WriteLine ( " б + |
ч л г е а trnath. DoAdd ( б, |
||||
Console . WriteLine ( " б - 2 |
{ О } " , |
rnath . DoSuЬ ( б, |
2 ) ) ; |
||
Console .WriteLine ( " б |
* 2 |
{ О } " , |
rnath. DoMul ( б, |
2 ) ) ; |
|
Console . WriteLine ( " б |
/ |
2 |
ж л со а trnath. DoDiv ( б , |
2 ) ) ; |
// Ожидаем подтверждения пользователя
Console . WriteLine ( "Haжмитe <Enter> для " +
Console . Read ( ) ;
"завершения программы. . . " ) ;
Вот вывод нашего тестового приложения:
6 |
+ |
2 |
= |
8 |
) |
|
и = |
|
|
|
|
|
= |
|
б |
/ |
2 |
= |
3 |
Нажмите |
<Enter> для завершения программы. . . |
Библиотеки зачастую предоставляют только статические методы. В этом случае инстанцировать библиотечный объект не нужно -
можно просто вызвать метод с помощью класса.
СОВЕТ
Дополнительные ключевые слова для управления доступом
Разделение программ на несколько сборок, как говорилось в предыдущих разделах, приводит к вопросу, какой код в AssemЬlyB доступен для обращения коду из AssemЬlyA. Примеры из главы 1 5, "Класс: каждый сам за себя", хорошо иллюстрируют применение ключевых слов puЫic и private. Но в этой главе я ничего не рассказал вам о других ключевых словах, управляющих доступом: protected, internal и комбинации protected internal. В следующих разде лах эта ситуация будет исправлена в предположении, что вы понимаете, что такое наследование и перекрытие методов, а также ключевого слова puЫic и private. Чтобы этот раздел имел для вас смысл, возможно, вам следует прочи тать (или перечитать) главу 1 5, "Класс: каждый сам за себя".
464 ЧАСТЬ 2 Объектно-ориентированное программирование на С#

Предположим, у нас есть программа с двумя проектами.
»Первый проект - выполнимая программа InternalLimitsAccess, класс которой Congress содержит метод Main ( ) , выполняющий программу (нет такого закона, чтобы класс метода Main ( ) обяза тельно назывался "Program").
»Второй проект - библиотека классов CIMssemЫy.
Вреальности Конгресс имеет раздражающую привычку лезть в дела ЦРУ
итребовать от него отчета и рассказа о своих секретах - понятно, только для конгрессменов и сенаторов. "Мы никому ничего не расскажем!" Подозритель ные же шпионы из ЦРУ боятся делиться своими секретами (наверняка они знают, из чего сделана кока-кола!) Допустим, что ЦРУ хотят сохранить свой самый главный секрет в полной тайне.
И тут начинаются проблемы. Все в ЦРУ должны знать этот секрет. В приме ре InternalLimitsAccess ЦРУ разделено на несколько классов, скажем, клас сы GroupA и GroupB. Представим, что это подразделения ЦРУ, которые иногда делятся секретами друг с другом. Предположим, что GroupA хранит некото
рый страшный секрет Х, помеченный как private (гриф "Перед прочтением сжечь!"). Код имеет примерно следующий вид:
цц |
|
a кт ,щктшrг:г : |
r((, |
р |
|
|
|||
(xш |
срк1щ, |
|
|
|
|
|
|
|
|
,ж |
|
:(ш |
р:, |
"ш:к нт n ,т |
|
|
|
||
|
|
|
|
|
|||||
|
|
цц |
|
|
|
|
|
|
|
цц |
:( |
сЕrr |
|
,г |
p |
|
|
|
|
т |
(rш |
Cщр |
тr |
|
|
|
|
||
|
тх: |
ш , |
|
щ1 :ктжми |
,(щ:рщг, |
rш:рщср(шсратшИцц |
ы V |
||
|
:кт |
,щкшCsщр тrн , |
,(э, |
:рщг rшрщср: |
(шсрrш. ы |
||||
т |
:( |
(uш |
Cщр |
тдд |
|
|
|
|
|
|
т |
D( |
р:, |
"р6рг, |
3:к1e: 36,(щ, gн , |
|
|
||
|
|
цц |
|
|
|
6,(щ, |
: |
|
|
ГЛАВА 20 Пространства имен и библиотеки 465

t !R!!,;AEj !! ,;!,;!!,R!p nr !d!!,; D!ER!!!! !!!!! Ал iWиn,;!eА
!!!!!!! !!!! ,! !!!!A !! E! Оt tm !! !!W ! Оnt iWde !!! !!d!i
|
,;!,;AD!!!! |
иЗtОо! !D! |
р d!,;!! ! m,;e! !! !!d!! |
!B!!! |
D!!!!!y |
||
ЗАПОМНИ! |
D!ER!!!d |
!!!!!d |
iWи |
eА,;! ! |
!!!о d!o,,; !!!,R !,;A!!!,;,! D |
||
|
|
|
|
|
|
|
|
|
!! D!! |
oi!d !,;!,;Ad!E!! |
D!D!!d |
!!D!!,;j !! !!!,;! |
!!!EL!p |
!!,!p |
|
|
!! !!! ! R!!!j,;!D! |
!!!,;!!,;!,;!,EL!! |
!! !p!,;!!t |
|
|
|
|
|
|
o П |
|
|
|
|
|
! |
! |
|
|
|
|
|
|
|
|
o М |
|
|
|
|
|
|
|
r ! |
!.i |
|
|
|
|
!.i |
! |
|
|
|
|
|
|
|
|
|
Н |
||
!!!!A D!!!! |
|
nЗtО!d! !,; !!!,;,! |
D!! D!!,;,z!! |
!!D!d, ! |
!!d !! !!!! D !Т |
||||||
!!!,;d d! d!E!,; |
!!!! |
D!B!,;AD!!!!, |
З |
Wtttn! |
d!,;!!! |
|
eАл ! |
,;! dtR,;! !! B!!!,; |
|||
i,;!,; !!D!!,; |
! !!E! |
!D !! ! !,t !! |
!!d |
!! D!!,; !! |
!! |
!! |
!!!,;t |
З tnWtt Di,;!d, |
|||
!! D!!,;, !,!!,;!,;A!! !! d!E!,;А |
|
|
|
|
|
|
|
||||
|
|
|
o |
|
П |
|
|
|
|
|
|
__a |
a |
a! |
uD e !!! |
!!!! |
Н |
!e a |
aa |
Dn |
!!! |
-! E |
t yfyf ЧАСТЬ 2 тЭфдгт еожо»вдеnв» оррееодиж»ощ»ряяв» орревдиерииси

|
-!РКИИПОИЗ!ОПО ЧТЕХТЕХe e! !И!НИА П! НЗЗС М МТ КИ!ИПС!ОЗАЕСПСЕМ |
||||
|
АО!CПОМКЗОЗЗАПИППОЗЗОНПМТЕХ! СНИ!И!НТ ЗЗОНПМ |
eЧТЕХe!0СОЗЕАМp |
|||
ЗАПОМНИ! |
СНИ!ЗАНП!БИАЗОЗОЗT, |
ЗАТЕХ |
|
|
|
О!ПО СОЕИАМАВЕИАО! П П!НЗЗИ |
ПНПЕ0 |
pПО ПН ЗНЕОЕ |
|||
|
|||||
|
!И!И ОППИ БП! ИАЗБ |
ТЕХ!ИПП!НЗЗН ПИЕО!ИА ЗСАВ ЗО!ИИ !ОЗАЕ |
|||
ЗАПОМНИ! |
СИПpКИИЕЗНЕ П!НЗЗpАНПКИАОАНПОЗАНППНКСПНИЕСЗ • |
o!ИПКИ ПН |
|||
ЗНЕОЕ !И!И БП!БИАЗБ |
|
ТЕХ |
|
||
|
|
|
n ПЗИИЧИ ЕО!ИА ТННПМАВЗПОМЗНЕСИ Ч!ЕЗОПИИaЗНЕСИ АИЕПСИ ЗИПНИАС ПАНЗПИОЗp )БП!ББ МТTТЕХ П!ЧТЕХЗПОИЕП!НЗЗИ! \АН ЗАННАИЧМБ! !НИА МТ!ОЗАЕС ПСЕМ АО!ВПОП .СОЕ П!НЗЗИТЕХ
protected: поделимся с подклассами
omp-2!-2!# 2(22(>#2(# |
ыМ |
esS-.,0-(,3 |
--#k trу,!-!62! |
th>(-,2!-,(k |
||||
-.,0-(,3 |
.#,(.( |
-21,,#22# |
,#(. |
2(я(( |
..(--(t |
С.(--0т .!,!,0# |
!--#.!-.#20 |
|
! -21,,#22#- |
-!.#,6(2(( |
.,1F(F |
..(--!-k |
2# -(-0# -#21>(# ..(--0 |
2( --#,#d |
ГЛАВА 20 Пространства имен и библиотеки 467

Дело в том, что в результате они оказываются "слишком тесно связанными" с классами, о которых слишком много знают. Если класс А знает о том, как рабо
тает внутри класс в, А может воспользоваться этим знанием. И при малейшем
изменении изменять придется оба класса.
Чем меньше другие классы и сборки знают о том, как класс в выполня ет свои обязанности, тем лучше. В главе 1 5, "Класс: каждый сам за себя", я использовал в качестве примера класс BankAccount. Банк не хочет изменять мой счет непосредственно. Счет - это закрытая часть реализации класса Ban kAccount . Класс Ban kAccount предоставляет доступ к счету - но толь ко с помощью тщательно контролируемого открытого интерфейса. В классе BankAccount открытый интерфейс состоит из трех открытых методов.
)) Метод Balance предоставляет способ получить значение текущего баланса. Это свойство только для чтения, так что им нельзя восполь зоваться для изменения значения баланса.
)) Метод Deposit ( ) позволяет строго контролируемо внести деньги на счет извне класса.
)) Метод Wi thdraw ( ) позволяет (в первую очередь, владельцу счета) снять со счета определенную сумму, но в строго контролируемых пределах. Withdraw ( ) обеспечивает выполнение бизнес-правила, которое заключается в том, что нельзя снять со счета больше, чем на нем есть.
Здесь используются только два ключевых слова - private и puЫic. Но в программировании бывают и иные ситуации. В предыдущем разделе вы виде ли, как ключевое слово internal открывает класс, но только другим классам в той же сборке.
Предположим, однако, что класс BankAccount имеет подкласс SavingsAc count. Методы в SavingsAccount требуют доступа к балансу, определенному в базовом классе. К счастью, savingsAccount может использовать открытый интерфейс, как и все другие классы, - воспользоваться свойством Balance и
методами Deposit ( ) и Withdraw ( ) .
Но иногда базовый класс не предоставляет такой доступ к своим внутрен ним делам для других. Что если член-данные _balance класса BankAccount объявлен как private и класс не предоставляет свойство Balance?
Воспользуемся ключевым словом protected. Если экземпляр пе ременной _balance в базовом классе объявить как protected, а не private, извне класса такая переменная будет недоступна, как и
ЗАПОМНИ! |
private. Но подклассы смогут с ней работать. |
|
-i DEi ЧАСТЬ 2 Объектно-ориентированное программирование на С#