- •Оглавление
- •Об авторе
- •Посвящение
- •Благодарности
- •Ждем ваших отзывов!
- •Что такое .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
- •Приступая к работе
- •Настройка проекта
- •Обработка счета
- •Создание подключения к событию
- •Рисование доски
- •Запуск новой игры
Вызов Write ( ) , в отличие от WriteLine ( ) , оставляет курсор сразу за введенной строкой. Это приводит к тому, что ввод пользователя на
ходится в той же строке, где и приглашение. Кроме того, добавление СОВЕТ символа новой строки ' \n ' создает пустую строку без необходимо
сти вызывать WriteLine ( ) .
Различие между объектами
Заводы в Детройте в состоянии выпускать множество автомобилей, отсле живать каждую выпущенную машину и при этом не путать их. Аналогично программа может создать несколько объектов одного и того же класса, как по казано в следующем фрагменте:
c,3: (r, (шхr |
. им, |
c,3 :( r, n т V |
|
(шх{ . г шим -ш(= |
=х,х== |
= |
|
|
= |
= = |
= |
|
= |
||
= |
= |
|
|
Создание объекта car2 и присваивание ему имени производителя Hudson никак не влияют на объект carl с именем производителя Studebaker. Это свя зано с тем, что carl и car2 находятся в разных местах памяти. Возможность различать объекты одного класса очень важна в работе с классами. Объект мо жет быть создан, с ним могут быть выполнены различные действия и он всегда выступает как единый объект, отличный от других подобных ему объектов.
Работа со ссылками
Оператор "точка" и оператор присваивания - это операторы, определенные для ссылочных типов. Рассмотрим следующий фрагмент исходного текста:
цц |
р |
хчшV |
|
c, 3:(x, |
|
||
цц |
|
c, 3:(u, n Н V |
|
р хчшх. им, |
|||
цц |
|
-ш( |
тх,хь1шг r, х ь V |
р хсшх. г шим |
|||
цц |
р |
х6тр |
: |
c, 3:(r, |
шшхrс = |
||
=п= Немного о классах 273
В первой строке создается объект yourcar, причем без присваивания ему значения. Такая неинициализированная ссылка называется дsед.х фыта.д .ь p=pы (null object). Любые попытки использовать неинициализированную ссылку приводят к немедленной генерации ошибки, которая прекращает выполнение программы.
Компилятор С# может перехватить большинство попыток использо вания неинициализированной ссылки и сгенерировать предупрежде ние в процессе компиляции программы. Если вам каким-то образом
mмуки#iи,м у, удалось провести компьютер, то обращение к неинициализирован
nnсu n а л
ной ссылке при выполнении программы приведет к ее аварийному останову.
Второе выражение создает новый объект Vehicle и присваивает его ссы лочной переменной yourcar. И последняя строка кода присваивает ссылке yourSpousalCar ссылку yourCar. Как показано на рис. 1 2. 1 , это приводит к тому, что yourSpousalCar ссылается на тот же объект, что и yourCar.
кну,rп.aоыь |
|
|
|
|
|
|
|
дтг, уаcи.а и. даг, |
|
чсзчюлс |
, |
|
|
||
nд.ьещпмхыхоыь, |
ийыtцхсмн, |
||
яВ |
|
|
|
Рис. 12. 1. Две ссылки на один и тот же объект
Эффект от следующих двух вызовов одинаков:
//Создание вашей машины
Vehicle yourCar = new Vehicle ( ) ; yourCar .model = "Kaiser";
//Эта машина принадлежит и вашей жене
Vehicle yourSpousalCar = yourCar;
//Изменяя одну машину, вы изменяете и другую yourSpousalCar .model = "Henry J" ;
Console .WriteLine ( "Baшa машина - " + yourCar . model ) ;
Выполнение данной программы приводит к выводу на экран названия мо дели Henry J, а не Kaiser. Обратите внимание на то, что yourSpousalCar не указывает на yourCar - вместо этого и yourSpousalCar, и yourCar указывают на один и тот же объект (одно и то же место в памяти). Кроме того, ссылка yourSpousalCar будет корректной, даже если окажется "потерянной" (напри мер, при выходе за пределы области видимости), как показано в следующем фрагменте:
oН i, |
,з.nф, н, eьe(хж оеaеля(ожялеыроое(, нле nлрттял еыроя (, ор, мч, |
В результате выполнения этого фрагмента исходного текста на экран выво дится сообщение "Ваша машина - Kaiser", несмотря на то что ссылка yourCar стала недействительной. Объект перестал быть ьл)e 2тA Ы(Р по ссылке yourcar. Но он не будет полностью недостижимым, пока не будут "потеряны"
или обнулены обе ссылки - и yourCar, и yourSpousalCar.
После этого - вернее будет сказать, в некоторый непредсказуемый момент после этого - )л 4l2r Р)л4) (garbage collector) С# вернет память, использо ванную ранее для объекта, все ссылки на который утрачены.
Возможность сделать одну лflreт 9 зl4lР lт! 9 (переменную ссылочного типа, такого как Vehicle или Student, в отличие от про
стого типа, такого как int или douЫe) указывающей на другой объ СОВЕТ ект - как это было сделано выше - делает работу со ссылочными
объектами в массивах и коллекциях и их хранение очень эффектив ными. Каждый элемент массива хранит ссылку на объект, и когда вы обмениваете элементы в массиве, то перемещаются только ссылки, но не сами объекты. Ссылки занимают фиксированное количество памяти, в отличие от объектов, на которые указывают.
Классы, содержащие классы
|
Члены класса могут, в свою очередь, быть ссылками на другие классы. На |
||||||||
пример, транспортное средство имеет двигатель, свойствами которого являют |
|||||||||
ся, в частности, мощность и рабочий объем. Можно поместить эти параметры |
|||||||||
непосредственно в класс Vehicle следующим образом: |
|
||||||||
т |
:) |
)rш |
c,4:)r, |
|
|
|
|
|
|
мt |
т |
u:) |
х:им1 |
длр,, r n |
,хW |
ц ц |
|
||
|
т |
:) |
х:им1 |
гшим |
.)ш |
цц |
|
||
|
т |
r;) |
:им |
им |
г,".ррх |
i |
цц |
|
|
|
т |
:) |
:им |
им |
г-, e4,, |
r |
s |
цц |
|
|
|
|
|
|
|
|
|
kьздз, i н , 5ктоеr е, е, aее(, |
бжеn |
Однако мощность и рабочий объем двигателя не являются свойствами ав |
|||||
томобиля, так как, |
например, джип моего сына может поставляться с одним |
||||
из двух двигателей с совершенно разными мощностями. Двигатель является |
|||||
самодостаточной концепцией и может быть описан отдельным классом: |
|||||
|
|
|
FF |
|
|
|
|
|
FF |
|
|
Вы можете внести этот класс в класс |
|
следующим образом: |
|||
|
|
|
FF |
|
|
|
|
|
F F |
|
|
|
|
|
F F |
|
|
|
|
|
F F |
|
|
Соответствен но, |
создание sonsCar теперь выглядит так: |
||||
// |
|
|
, , |
|
|
, |
• |
ЬQ |
|
|
|
|
|
|
|||
, |
|
б |
, Q |
|
|
FF |
|
|
ь |
|
|
, |
т |
|
|
|
|
|
д |
|
|
||
) |
|
ж |
т |
|
|
, |
|
|
|
|
|
, |
|
а |
|
|
|
F F |
|
|
|
|
|
, |
|
|
|
|
|
Доступ к рабочему объему двигателя из |
можно получить в два эта |
||||
па, как показано в приведенном далее фрагменте: |
|||||
, |
, |
|
|
|
|
" ьд |
|
ии, |
m |
, |
|
Однако можно получить эту величину и непосредственно: |
|||||
, |
ь з |
|
и |
m |
|
|
|
|
К, |
|
|
|
|
, |
, |
|
|
любом случае доступ к значен ию |
|
осуществляется через |
|||
класс Motor. |
|
|
|
|
|
таюС
хля#. |
и |
дьп"хео |
,оивпехвиознееоп |
ои обинтт виозневп |
ен na |
Статическ1Y1 е ие чш лены класса
ч
Большинство членов-данных описывают отдельные объекты. Рассмотрим следующий класс м,яt3
т |
:( |
))rш |
пшх |
|
т |
r:( |
==имх1 r:( ,им ,rш ,W"" |
Номерной знак является ),л,)e, Y лflreNe описывающим каждый авто мобиль и уникальным для каждого автомобиля. Присваивание номерного зна ка одному автомобилю не меняет номерной знак другого:
пшх |
тр |
,пшх. им, пшх н sW |
||||
тр |
шх,п" r:( ,им |
,,rш |
., |
тftik: л C т W |
||
пшх |
р |
хпшх. |
им, |
пшх n sW |
.:Vу V |
|
р |
шххп. r I( ,им |
,,rш |
., т |
|||
Однако имеются и такие свойства, которые присущи всем автомобилям. На пример, количество выпущенных автомобилей является свойством класса м,яо3 но не отдельного объекта. 1,л ,)e,л r" N))N помечается специальным ключе вым словом :,,аъян3 как показано в следующем фрагменте исходного текста:
т |
:( |
(rш |
пшх |
|
|
|
т |
rI( |
ы I;*им им |
и,х,-пшх a |
"" гл |
|
т |
:( |
х1 :имr : (,им |
,,rш ,W |
"" |
Обращение к статическим членам выполняется не посредством объ екта, а через сам класс, как показано в следующем фрагменте исход
ного текста:
ЗАПОМНИ!
З
Обращение к члену объекта ,тuм ,) бr3ъ лт,ут.t,ат3 выполняется посредством объекта ,тu м,)я3в то время как обращение к (статическому) члену н,) зy3.т )сo3 м , ) A 3 осуществляется с помощью имени класса. Все объекты типа м , ) 3 совместно используют один и тот же член yua б т ) с o м , ) у т 3так что каждый автомобиль содержит то же самое значение этого члена, что и все прочие автомобили.
koздз, э н , 5ктое Ые, е, хВреер(, |
лl, |
