Вы находитесь на странице: 1из 689

Изучаем

2-е издание
Управляй
данными Познай секреты
с Ы № абстрагирования
и наследования /

Изучай С#
на забавных ^
примерах

Узнай,
как методы Научись
расширения эффективно
облегчают жизнь использовать
программиста обобщенные
коллекции
Изучаем С#
2-е издание

Э. Стиллмен
Дж. Грин

С ^ П П Т Е Р '
М о скв а ■С а н кт-П е т е р б у р г ■Н и ж н и й Н о вгород ■В о р о н еж
Р о с то в -н а -Д о н у • Е ка тер и н б ур г ■С а м а р а - Н о в о си б и р ск
К и ев • Х арь ков ■М и н с к
2012
ББК 32.973.2-018.1
УДК 004.43
С80

Стиллмен Э., ГринДж.


С80 Изучаем С#. 2-е изд. — СПб.: Питер, 2012. — 696 с.: ил.

ISB N 978-5-459-00422-9

В отличие от большинства книг по программированию, построенных на основе скучного изложения спе­


цификаций и примеров, с этой книгой читатель сможет сразу приступить к написанию собственного кода на
языке программирования C# с самого начала. Вы освоите минимальный набор инструментов, а далее приме­
те участие в забавных и интересных программных проектах: от разработки карточной игры до создания серь­
езного бизнес-приложения. Второе издание книги включает последние версии C# .NET 4.0 и Visual Studio
2010 и будет интересно всем изучающим язык программирования С#.
Особенностью данного издания является уникальный способ подачи материала, выделяющий серию «Head
First» издательства O’Reilly в ряду множества скучных книг, посвященных программированию.

ББК 32.973.2-018.1
УДК 004.43

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

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

ISBN 978-1-4493-8034-2 англ. © Authorized Russian translation of the English edition Head First C# © O'Reilly
Media, Inc. This translation is published and sold by permission of O'Reilly Me­
dia, Inc., the owner of all rights to publish and sell the same
ISBN 978-5-459-00422-9 © Перевод на русский язык ООО Издательство «Питер», 2012
© Издание на русском языке, оформление
ООО Издательство «Питер», 2012
авторы

Спасибо, что купили нашу книгу!


М ы писали ее с удовольствием
и надеемся, что вы получите
кайф от ее Прочтения...

Эндрю

А в т о р эт о й ф о т о гр а ф и и (как
и с н и м ка канала Гованус) ~
Ниша Сондхе

Э ндрю С тиллм ен родился в Нью-Йорке,


дважды ему приходилось жить в Питтсбурге.
Сначала он закончил там университет Карне-
ги-Меллон, затем именно вэтом городе они
с Дженни начали свой консультационный
бизнес и работу над первой книгой для изда­ Д ж ен н и ф ер Грин изучала в колледже фило­
тельства O ’Reilly софию и, как и многие ее однокурсники, не смог­
ла найти работу по специальности. Но благодаря
Вернувшись после колледжа в родной город,
способностям к разработке программного обеспе­
Эндрю устроился программистом в фирму
чения она начала работать в онлайновой службе.
EMI-Capitol Records, что было не лишено
смысла, ведь в школьные годы он научился В 1998 году Дженни переехала в Нью-Йорк и
играть на виолончели и джазовой бас-гитаре. устроилась в фирму по разработке финансово­
И в той же компании, где Эндрю руководил го программного обеспечения. Она управляла
командой программистов, работала Джен­ командой разработчиков, занимавшихся искус­
ни. За прошедшие годы Эндрю сотрудничал ственным интеллектом и обработкой естествен­
с весьма квалифицированными программи­ ных языков.
стами и уверен, что многому от них научился. Затем она много путешествовала по миру с раз­
В свободное от написания книг время Эндрю личными командами разработчиков и реализова­
создает бесполезные (но забавные) програм­ ла целый ряд замечательных проектов.
мы, пишет музыку (для видеоигр и не толь­ Дженифер обожает путешествия, индийское
ко), изучает тайцзи и айкидо, встречается со кино, комиксы, компьютерные игры и свою гон­
своей девушкой Лизой и выраш;ивает шпица. чую.

с момента своей встречи в г я я г - м Дженни и Эндрю вместе разрабатывают программное обе­


спечение и пиш ут о нем. Их первая книга Applied Software Project ^
стве О'Рейли в ZOOS году. A первая книга в серии Head P in t Head R rst РМР поябылясь б Z 007-M .
В Z 0 0 3 году ребята основали ф ирму Stellm an & Qreene Consultine ^о разработке програм мно­
го обеспечения для ученых, исследующих воздействие гербицидов, примененных во время ^^ины во
Вьетнаме В свободное от написания программ и книг время Эндрю и Джени участ вую т в конфе
рент ах разработчиков программного обеспечения и руководителей проектов.
Их личный блог расположен по адресу: http://w w w .stellm an-greene.com
оглавление

О одерж ание (с Б о д к а )

Введение 23
1 Эффективность с с#. Визуальные приложения за 10 минут 35

2 Это всего лишь код. Под покровом 73


3 Объекты, по порядку стройся! Приемы программирования 115
4 Типы и ссылки. 10:00утра. Куда подевались наши данные? 153
5 Инкапсуляция. Пусть личное остается... личным 195
6 Наследование. Генеалогическое древо объектов 231
7 И нтерфейсы и абстрактные классы. Пусть классы держат обещания 283
8 Перечисления и коллекции. Большие объемы данных 339
9 Чтение и запись файлов. Сохрани массив байтов и спаси мир 395

10 Обработка исключений. Борьба с огнем надоедает 449


11 События и делегаты. Что делает ваш код, когда вы на него не смотрите 491
12 Обзор и предварительные результаты. Знания, сила и построение
приложений 525
13 Элементы управления и графические фрагменты. Наводим красоту 573
14 Капитан Великолепный. Смерть объекта 631
15 ЫЫЦ. Управляем данными 669

( ^ о д е |^ Ж а н и е ( н а с л іо й г Щ е е )

Введение
Ваш мозг и С # . Вы учитесь — готовитесь к экзамену. Или
пытаетесь освоить сложную техническую тему. Ваш мозг пытается
оказать вам услугу. Он старается сделать так, чтобы на эту оче­
видно несущественную информацию не тратились драгоценные
ресурсы. Их лучш е потратить на что-нибудь важное. Так как же за­
ставить его изучить С # ?
Для кого написана эта книга 24
Мы знаем, о чем вы думаете 25
Метапознание: наука о мышлении 27
Заставьте свой мозг повиноваться 29
Что вам потребуется 30
Информация 31
Технические рецензенты 32
Благодарности 33

7
оглавление

э ^ '^ е К т и Б н о с ш ь С

Визуальны е приложения з а 10 минут


Хотите программировать действительно быстро? с# — это
мощный язык программирования. Благодаря Visual Studio вам не потре­
буется писать непонятный код, чтобы заставить кнопку работать. Вместо
того чтобы запоминать параметры метода для имени и для ярлыка кнопки,
вы сможете сфокусироваться на достижении результата. Звучит заманчи­
в о ? Тогда переверните страницу и приступим к делу.

Зачем вам изучать C# 36


с#, ИСР Visual Studio многое упрощают 37
Избавьте директора от бумаг 38
Перед началом работы выясните, что именно нужно пользователю 39
Что мы собираемся сделать 40
Это вы делаете в Visual Studio 42
А это Visual Studio делает за вас 42
Создаем пользовательский интерфейс 46
Visual Studio, за сценой 48
Редактирование кода 49

Первый запуск приложения 50


Где же мои файлы? 50

Вот что уже сделано 51

Для хранения информации нужна база данных 52


База данных, созданная ИСР 53
Язык SQL 53

Создание таблицы для списка контактов 54


Поля в контактной карте —это столбцы таблицы People 56
Завершение таблицы 59

Перенос в базу данных с карточек 60


Источник данных соединит форму с базой 62
Добавление элементов, связанных с базой данных 64
.NET Framework lerigelsimd
solutione
Howeood? Ooood OtШ яг Швая Хорошие программы понятны интуитивно 66
Vrfua ...... 7
Тестирование 68

D
«П(« Как превратить ВАШЕ приложение в приложение для ВСЕХ 69
Передаем приложение пользователям 70
Oala access
Работа НЕ окончена: проверим процесс установки 71
Управляющее данными приложение готово 72
оглавление

э щ о Б сеГ о Л и Ш ь К оД

Под покровом
Вы — программист, а не просто пользователь
ИСР. И С Р может сделать за вас многое, но не всё. При на­
писании приложений часто приходится решать повторяющиеся
задачи. Пусть эту работу выполняет ИСР. Вы же будете в это
время думать над более глобальными вещами. Научившись
писать код, вы получите возможность решить любую задачу.

Когда вы делаете это... 74


...ИСР делает это. 75
Как рождаются программы 76
Писать код помогает ИСР 78
Любые действия ведут к изменению кода 80
Структура программы 82
Начало работы программы 84
Редактирование точки входа 86
Д°СЗЦр“Ц1Це ЬСлассы могут принадлежать одному пространству имен 91
ишкую f o J ^ 92
Что такое переменные

♦ Знакомые математические символы 94


Наблюдение за переменными в процессе отладки 95
Циклы 97
Перейдем к практике 98
О ператор выбора 99
П роверка условий 100

А л я т х д с й програм м ы вк

Р™ , « Ч Е Т

(Сля£;с имен
ф р а гм е н т бйиде«
(омен»
АМХА&неки&л^ограммы ^
могитCOC^v\oi:^A\t:>
и з й е г о о д н о го к л а с с а ;.

К л а с с в ю \к / ч а е у л о Зми и л и н с с к о л о к о
A^£Уv'.o^oв. M£^■vxoдo^всегё^а
какому-либо
'Л из о м р а ь у ^ о р о в ,
оглавление

о б ъ е к т ы , 310 ц о|> яд ку сшр>ойся

Приемы программирования
Каждая прогроАлма решает какую-либо проблему. Перед на­
писанием программы нужно четко сформулировать, какую задачу она будет
решать. Именно поэтому так полезны объекты. Ведь они позволяют струк­
турировать код наиболее удобным образом. Вы же можете сосредоточить­
ся на обдумывании путей решения, так как вам не нужно тратить время на
написание кода. Правильное использование объектов позволяет получить
интуитивно понятный код, который при необходимости можно легко отре­
дактировать.

Что думает Майк о своих проблемах 116


Проблема Майка с точки зрения навигационной системы 117
Методы прокладки и редактирования маршрутов 118
Построим программу с использованием классов 119
Идея Майка 121
Объекты как способ решения проблемы 122

Нау|да1ог Возьмите класс и постройте объект 123


8 е10е811па1юп() Экземпляры 124
ModifyRouteToAvoid()
Мо(11^Рои1еТо1п(:^ис1е() Простое решение! 125
6е1Нои1е()
ве1ПтеТоОе811паИоп() Поля 130
То1а101з1апсе()
Создаем экземпляры! 131
Спасибо за память 132
Что происходит в памяти программы 133
Значимые имена 134
Структура классов 136
Выбор структуры класса при помощи диаграммы 138
Определяй «лйсс, вы определяете Помогите парням 142
и его мскУ\оды, точно также как
чертеж 01лределяет внешний вид П роект «Парни» 143
дома.
Форма для взаимодействия с кодом 144
Более простые способы присвоения начальных значений 147

чН а основе одного чертежа


МОЖНО у^остроить сколько
угодно домов, а из одного
класса можно получить
сколько угодно объектов.
10
оглавление

гоипь! и ссылки

L
10:00 утра. Куда подевались наши данны е?
Без данных програллмы бесполезны. Взяв информацию от поль­
зователей, вы производите новую информацию, чтобы вернуть ее им же.
Практически все в программировании связано с обработкой данных тем
или иным способом, в этой главе вы познакомитесь с используемыми в С #
типами данных, узнаете методы работы с ними и даже ужасный секрет объ­
ектов (только т-с-с-с... объекты — это тоже данные).

Тип переменной определяет, какие данные она может сохранять 154


Наглядное представление переменных 156
10 литров в 5-литровой банке 157
Приведение типов 158
Автоматическая коррекция слишком больших значений 159
Иногда приведение типов происходит автоматически 160
Аргументы метода должны быть совместимы
с типами параметров 161
Комбинация с оператором = 166
Объекты тоже используют переменные 167
Переменные ссылочного типа 168
Ссылки подобны маркерам 169
П ри отсутствии ссылок объект превращается в мусор 170
Побочные эффекты множественных ссылок 171

Dog fldo; Две ссылки это ДВА способа редактировать данные объекта 176
Dog lucky new Do g (); Особый случай; массивы 177
Массив 177
Массив может состоять из ссылочных переменных 178
Добро пожаловать на распродажу сэндвичей от Джо! 179
fido = new D o g O ;
Ссылки позволяют объектам обращаться друг к другу 181
Сюда объекты еще не отправлялись 182
Играем в печатную машинку 187

lucky = null;
poof!-~
/ \ \

11
оглавление

инкапсуляция

Пусть личное остается... личным

Вы когда-нибудь мечтали о том, чтобы вашу личную


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

Кэтлин профессиональный массовик-затейник 196


Как происходит оценка 197

Кэтлин тестирует программу 202


Каждый вариант нужно было считать отдельно 204
Неправильное использование объектов 206
Форма 206
Инкапсуляция как управление доступом к данным 207
Доступ к методам и полям класса 208
НА САМОМ ЛИ ДЕЛЕ защищено поле realName? 209
Закрытые поля и методы доступны только изнутри класса 210
Инкапсуляция сохраняет данные нетронутыми 218
Инкапсуляция при помощи свойств 219
Приложение для проверки класса Farmer 220
Автоматические свойства 221
Редактируем множитель feed 222
Конструктор 223

Ш еШ ю і». FuKy
(•їрсгріпм '' №oratloHi

WMbervf
peo^e.
ыт
AluikU«t
СтНїівв:
fSAieowitoH
total cut)
Pamv
raney
deeoratioH^
> І*і;рсггіпм
•VOdutrathig
ful
i=oo4»2$|i<r
(НГМЯ) NomuU
АМЫ, Picontlnu
(*20|ИГ №ЇОр(Г
liemid
s s s s a is i

12
оглавление

наследование

Генеалогическое древо объектов


Иногда люди хотят быть похожим на своих родителей.
Вы встречали объект, который действует почти так, как нуж но? Думали ли вы
о том, какое совершенство можно бы ло бы получить, изменив всего несколько
элем ентов? Именно по этой причине наследование является одним из самых
мощ ных инструментов с#, в этой главе вы узнаете, как производный класс
повторяет поведение родительского, сохраняя при этом гибкость редактиро­
вания. Вы научитесь избегать дублирования кода и облегчите последующее
редактирование своих программ.

Организация дней рождения —это тоже работа 1Сэтлин 232


Нам нужен класс BirthdayParty 233
Планировщик мероприятий, версия 2.0 234
Дополнительный взнос за мероприятия с большим
количеством гостей 241
Наследование 242
Модель классов; от общего к частному 243
Симулятор зоопарка 244
Иерархия классов 248
Производные классы расширяют базовый 249
Синтаксис наследования 250
П ри наследовании поля свойства и методы базового класса
добавляются к производному... 253
П ерекрытие методов 254
Вместо базового класса можно взять один из производных 255
Производный класс умеет скрывать методы 262
Ключевые слова override и virtual 264
Ключевое слово base 266
Если в базовом классе присутствует конструктор, он должен остаться
и в производном классе 267
Теперь мы готовы завершить программу для Кэтлин! 268
Система управления ульем 273
П остроение основ 274
Совершенствуем систему управления ульем
при помощи наследования 282

13
оглавление

интер^^ейсы и а^ аи р ак тн ы е классы

Пусть классы держат обещания


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

Наследование
Вернемся к нашим пчелам 284
Классы для различных типов пчел 285
И нтерфейсы 286
ДбсторакЦия
Классы, реализующие интерфейсы, должны включать ВСЕ
методы интерфейсов 289
^|нкаисуляЦия Ф Учимся работать с интерфейсами 290
Ссылки на интерфейс 292
Ссылка на интерфейс аналогична ссылке на объект 293
IJoiuMop'fuaM Интерфейсы и наследование 295
КоЬоВее 4000 функционирует без меда 296
Locsl&on Кофеварка относится к Приборам 298
Name
Exfts Восходящее приведение 299
Нисходящее приведение 300
Oescrip&mO
Нисходящее и восходящее приведение интерфейсов 301
Модификаторы доступа 305
R oom O utsid e
Decoration Hot Изменение видимости при помощи модификаторов доступа 306
Классы, для которых недопустимо создание экземпляров 309
Абстрактный класс. Перепутье между классом и интерфейсом 310
Как уже было сказано, недопустимо создавать экземпляры
некоторых классов 312

Абстрактный метод не имеет тела 313


Смертельным ромбом! 318

Различные формы объекта 32 1

14
оглавление

п е р е ч и с л е н и я U К о л л е к ц и и

Большие объемы данных


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

Категории данных не всегда можно сохранять


в переменных типа string 340
Перечисления 341
Присвоим числам имена 342
Создать колоду карт можно было при помощи массива... 345
Проблемы работы с массивами 346
Коллекции 347
Коллекции List 348
Динамическое изменение размеров 351
Обобщенные коллекции 352
Инициализаторы коллекций 356
Коллекция уток 357
Сортировка элементов коллекции 358
И нтерфейс IComparable<Duck> 359
Способы сортировки 360
Создадим экземпляр объекта-компаратора 361
Сложные схемы сравнения 362
П ерекрытие метода ToStringO 365
Обновим цикл foreach 366
\ \ ^ Интерфейс1ЕпитегаЫ е<Т> 367
- ___ Восходящее приведение с помощью lEnum erable 368
* Создание перегруженных методов 369
/ ^ Словари 375
Дополнительные типы коллекций... 389
Звенья следуют в порядке их поступления 390
Звенья следуют в порядке, обратном порядку их поступления 391

15
оглавление

Ч тение U san u cb * ^ a u JIo B

Сохрани м ассив байтов и сп аси мир


Иногда настойчивость окупается.
Пока что все ваши программы жили недолго. Они запускались, некоторое вре­
мя работали и закрывались. Но этого недостаточно, когда имеешь дело с важ­
ной информацией. Вы должны уметь сохранять свою работу В этой главе мы
поговорим о том, как записать данные в файл, а затем о том, как прочитать эту
информацию. Вы познакомитесь с потоковыми классами .N ET и узнаете о тай­
нах шестнадцатеричной и двоичной систем счисления.

Для чтения и записи данных в .NET используются потоки 396


Различные потоки для различных данных 397
Объект FileStream 393

Трехшаговая процедура записи текста в файл 399


Чтение и запись при помощи двух объектов 403
Встроенные объекты для вызова стандартных окон диалога 407
Встроенные классы File и Directory 4 Ю
Открытие и сохранение файлов при помощи окон диалога 413
И нтерфейс IDisposable 415

Операторы using как средство избежать системных ошибок 416


Запись файлов сопровождается принятием решений 422
О ператор switch 423

Ч тение и запись информации о картах в файл 424


Чтение карт из файла 425

Сериализации подвергается не только сам объект... 429

69 117 114 101 107 97 33


Сериализация позволяет читать и записывать объект целиком 430
E u re k a ! Сериализуем и десериализуем колоду карт 432
о \ г г ^ ч i
.NET использует Unicode для хранения символов и текста 435
Перемещение данных внутри массива байтов 436
Класс BinaryWriter 437

Чтение и запись сериализованных файлов вручную 439


Найдите отличия и отредактируйте файлы 440
69 7^4 Сложности работы с двоичными файлами 441
10797' Программа для создания дампа 442

Достаточно StreamReader и Stream Writer 443


Чтение байтов из потока 444

16
оглавление

обр>абощ ка искЛ іоЧ ений

Борьба с огнем надоедает


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

Брайану нужны мобильные оправдания 450


Объект Exception 454
Код Брайана работает не так, как предполагалось 456
Исключения наследуют от объекта Exception 458
Работа с отладчиком 459
Поиск ошибки в приложении Excuse Manager с помощью
отладчика 460
А код все равно не работает... 463
Ключевые слова try и catch 465
Вызов сомнительного метода 466
Результаты применения ключевых слов try/catch 468
Ключевое слово finally 470
Получения информации о проблеме 475
Обработка исключений разных типов 476
Один класс создает исключение, другой его обрабатывает 477
Исключение O utO ffloney для пчел 478
Оператор using как комбинация
операторов try и finally 481
Избегаем исключений при помощи интерфейса IDisposable 482
Наихудший вариант блока catch 484
Временные решения 485
Краткие принципы обработки исключений 486
Наконец Брайан получил свой отдых... 489

17
оглавление

собьдпия и ДеЛеГашь!

Что делает код, когда вы на него не смотрите


Невозможно все время контролировать созданные объекты.
Иногда что-то... происходит И хотелось бы, чтобы объекты умели реагиро­
вать на происходящее. Здесь вам на помощь приходят события. Один объ­
ект их публикует, другие объекты на них подписываются, и система работает.
А для контроля подписчиков вам пригодится метод обратного вызова.

Хотите, что объекты научились думать сами? 492


Как объекты узнают, что произошло? 492
События 493
Один объект инициирует событие, другой реагирует на него 494
Обработка события 495
Соединим все вместе 496
Автоматическое создание обработчиков событий 500
Обобщенный ЕуепСНап(11ег 506
Все формы используют события 507
Несколько обработчиков одного события 508
Связь между издателями и подписчиками 510
Делегат замещает методы 511
Делегаты в действии 512
Объект может подписаться на событие... 515
Обратный вызов 516
О братный вызов как способ работы с делегатами 518

Р‘^с с ^о я н и и 8 2 о т базы. Лодаюм,ий Эолжен


^ I б роси т о э т о т
Ва11 .О пВ аШ п Р 1ау (70, 82) МЯИ.
^ Подаю щ ий м ож ет

у г л о м и на
т а к о е расст оя н и е
дольш е, чем 28 32 .).

Р 1 Ь с Ь в г .С а Ь с Ь В а 1 1 (7 0 , 90)

18
оглавление

и т1реДБа|=пщ1еЛьНые р’езуЛ ьташ ы

Знания, си ла и построение приложений


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

Жизнь U смерть цветка Вы прошли долгий путь 526


Вы стали пчеловодом 527
Архитектура симулятора улья 528
jage = О Ife
П остроение симулятора улья 529
Ж изнь и смерть цветка 533
Класс Вее 534
Программисты против бездомных пчел 538
Для жизни улья нужен мед 538
П остроение класса Hive 542
Метод Go О для улья 543
Все готово для класса World 544
Система, основанная на кадрах 545
Код для класса World 546
Поведение пчел 552
Основная форма 554
Получение статистики 555
Обье^г^
Таймеры 556
Работа с группами пчел 564
Коллекция коллекционирует... ДАННЫЕ 565
LINQynpom;aeT работу с коллекциями и базами данных 567
Тестирование (вторая попытка) 568
Последние штрихи: O pen и Save 569

O&beV^

19
оглавление

элем енты уп|>аБления и Гра^^иЧеские “^ а Ш е н т ы

Наводим красоту

Иногда управление графикой приходится брать в свои руки.


До этого момента визуальный аспект наших приложений был отдан на откуп
элементам управления. Но иногда этого недостаточно, например, если вы
хотите анимировать изображение. Вам предстоит научиться создавать свои
элементы управления для .NET, применять двойную буферизацию и даже
рисовать непосредственно на формах.

Элементы управления как средство взаимодействия


с программой 574
Элементы управления - это тоже объекты 575
Анимируем симулятор улья 576
Визуализатор 578
Формы для визуализации 579
Первый анимированный элемент управления 583
Базовый класс PictureBox 584
Кнопка добавления элемента BeeControl 586
Удаление дочерних элементов управления 587
Класс UserControl 588
Поместим на форму анимированных пчел 590
Формы Hive и Field 592
П остроение визуализатора 593
Соединим основную форму с формами HiveForm и FieldForm 596
Проблемы с производительностью 600
Объект Graphics 602
Объект Bitmap 603
Пространство имен System.Drawing 604
Знакомство с GDI+ 605
Рисуем на форме 606
Решение проблемы с прозрачностью 611
Событие Paint 612
П ерерисовка форм и элементов управления 615
Двойная буферизация 618
Вывод на печать 624
Окно предварительного просмотра и окно диалога Print 625

20
оглавление

Метод завершения объекта 638


Когда запускает метод завершения объекта 639
Явное и неявное высвобождение ресурсов 640
Возможные проблемы 642
Сериализуем объект в методе Dispose () 643
Структура напоминает объект... 647
...но объектом не является 647
Значения копируются, а ссылки присваиваются 648
Структуры - это значимые, а объекты - ссылочные типы 649
Сравнение стека и кучи 651
Необязательные параметры 656
Типы, допускающие значение null 657
Типы, допускающие значение null, увеличивают робастность
программы 658
Что осталось от Великолепного 661
Сравнение 661
Методы расширения 662
Расширяем фундаментальный тип; string 664

21
оглавление

LINQ
Управляем данными
Этот мир управляется данными... вам лучше знать, как в нем жить.
Времена, когда можно бы ло программировать днями и даже неделями, не
касаясь множества данных, давно позади. В наши дни с данными связано
все. Часто приходится работать с данными из разных источников и даже раз­
ных форматов. Базы данных, XM L, коллекции из других программ... все это
давно стало частью работы программиста на С#. В этом ему помогает LINQ.
Э та функция не только упрощ ает запросы, но и умеет разбивать данные на
группы и, наоборот, соединять данные из различных источников.

Простой проект... 670


...но сначала нужно собрать данные 671
List<StarbuzzData> 671
Сбор данных из разных источников 672
Коллекции .NET уже настроены под LINQ 673
Простой способ сделать запрос 674
Сложные запросы 675
Универсальность LINQ 678
Группировка результатов запроса 683
Сгруппируем результаты Джимми 684
Предложение join 687
List<Comic> 687
LIN Q Sequence 687
List<Purchases> 687
Джимми изрядно сэкономил 688

LINQ Sequence 689


List<StarbuzzData> 689
Соединение LINQ с базой данных SQL 690
Ч Соединим Starbuzz и Objectville 694

22
к а к р а б о зза а ш ь с эш ^ й к н и Г о й

Введение

в э т о м розЭеле " т А 1^^0 6 ^ к ™ га ° С*?»


« т а к п ом ем у они бклю иил
как работать с этой книгой

Для кого написана эта книга?


Е сли н а воп росы :

Вы хотите изучать С#?

Вы предпочитаете учиться практикуясь, а не просто


читая текст?

Вы предпочитаете оживленную беседу сухим,


скучным академическим лекциям?

вы о тв е ч а е те п о л о ж и тел ьн о , то эта кн и га для вас.

Кому эта книга не подойдет?


Если вы ответите «да» на любой из следующих вопросов.

^ Навевает ли на вас скуку и нервозность мысль о том,


что придется часто и много писать код?

Вы отличный программист на C++ или Java,


которому нужен справочник?

^ Вы боитесь попробовать что-нибудь новое? Скорее


пойдете к зубному врачу, чем наденете полосатое
с клетчатым? Считаете, что техническая книга, в которой
концепции 0# изображены в виде человечков, серьез­
ной быть не может?

...эта книга не для вас.

[З а м е т к а о т о т д ела продаж-
в о о б щ е -т о эт а кныга для лю бого
У кого е с т ь деньги.]

24 введение
введение

Mbl знаем, о чем Вы думаете


«Разве серьезные книги по программированию на C# такие?»
«И почему здесь столько рисунков?»
«Можно ли так чему-нибудь научиться?» М озг ги,

^^Ж но. ^
U мы знаем, о чем думает Ваш мозг /
Мозг жаждет новых впечатлений. Он постоянно ищет,
анализирует, ожидает чего-то необычного. Он так устроен, и это
помогает нам выжить.
В наши дни вы вряд ли попадете на обед к тигру. Но наш мозг
постоянно остается настороже. Просто мы об этом не знаем.
Как же наш мозг поступает со всеми обычными, повседневными
вещами? Он всеми силами пытается оградиться от них, чтобы
они не мешали его настоящей работе —сохранению того, что
действительно важно. Мозг не считает нужным сохранять
скучную информацию. Она не проходит фильтр, отсекающий
«очевидно несущественное».
Но как же мозг узнает, что важно? Представьте, что вы выехали
на прогулку, и вдруг прямо перед вами появляется тигр. Что
происходит в вашей голове и в теле?
Активизируются нейроны. Вспыхивают эмоции. Происходят
химические реакции.
И тогда ваш мозг понимает...

Конечно, это важно! Не забывать!


А теперь представьте, что вы находитесь дома или в библи­
отеке, в теплом, уютном месте, где тигры не водятся. Вы
учитесь —готовитесь к экзамену. Или пытаетесь освоить
сложную техническую тему, на которую вам выделили не­
делю... максимум десять дней.
И тут возникает проблема: ваш мозг пытается оказать вам
услугу. Он старается сделать так, чтобы на эту очевидно несу­
щественную информацию не тратились драгоценные ресур­
сы. Их лучше потратить на что-нибудь важное. На тигров,
например. Или на то, что к огню лучше не прикасаться.
Или что ни в коем случае нельзя вывешивать фото с этой
вечеринки на своей страничке в Facebook.
Нет простого способа сказать своему мозгу: «Послушай,
мозг, я тебе, конечно, благодарен, но какой бы скучной ни была
эта книга, и пусть мой датчик эмоций сейчас на нуле, я хочу
запомнить то, что здесь написано».

д ал ьш е > 25
как работать с этой книгой

V a к н и г а ДЛЯ г о е - . Н™ £ 5

к а к « ы ч т о -т о "^ к о
Затолкать в голову поболь Ф g ^огии и психологии обучения, для

М ы знаем, как заставить ваш мозг работать.

О с н о в н ы е п р и н ц и п ы с е р и и « H e a d F ir s t » ;
наглядность. Графика запоминается гораздо лучше, чем о б ьн ны и

V o I

- »-»пож ения. Недавние исследования показали,


р а з г о в о р н ы й с т и л ь и з л о * о (вместо
« и я . » фор«льныхл«цш
™ „е
),лучш ей.»
.о п р .р а ,г о з о р „ о » с т и „ е _ ~ ^
результатов на итоговом тестиров относитесь к себе слишком


столом или лекция?
Ппка вы не начнете напрягать извилины,
А кти вное участие чит ‘ читатель должен быть заинтере-
в вашей голове ничего не п р о ф ормулировать выводы
сован в результате; он долж р g д^^^лы упраж нения и

= е Г п " ; „ : = ^ ^

мозга и разные чувства.

Привлечение (и ой странице». М озг обращ ает внимание на инте-


очень хочу изучить это, но зась. неожиданное. Изучение слож ной техниче-

А
•Х -= Е
Г = Г о , . т е ^ и ^

\ ;г :;г г г ::;« ч » .с е ,„ ,й к .5 о а

26 введение
введение

Метапознание: наука о мышлении


Если вы действительно хотите быстрее и глубже усваивать новые
знания —задумайтесь над тем, как вы задумываетесь. Учитесь учиться.
Мало кто из нас изучает теорию метапознания во время учебы. Нам
положеноучитъся, но нас редко этому учат.
Но раз вы читаете эту книгу, то, вероятно, вы хотите узнать, как
программировать на С#, и по возможности быстрее. Вы хотите
запомнить прочитанное и применять новую информацию на практике.
Чтобы извлечь максимум пользы из учебного процесса, нужно
заставить ваш мозг воспринимать новый материал как Нечто Важное.
Критичное для вашего суш;ествования. Такое же важное, как тигр.
Иначе вам предстоит бесконечная борьба с вашим мозгом,
который всеми силами уклоняется от запоминания новой
информации.

К а к ж е У Б Е Д И Т Ь м о зг, ч т о п р о г р а м м и р о в а н и е н а С #
та к ж е в аж но, как и ти гр ?
Есть способ медленный и скучный, а есть быстры й и
эфф ективны й. П ервы й основан на тупом повторении.
Всем известно, что даже самую скучную инф ормацию можно
запомнить, если повторять ее снова и снова. П ри достаточном
количестве повторений ваш мозг прикидывает: «Вроде бы несущественно,
но раз одно и то же повторяется столько раз... Ладно, уговорил».
Быстрый способ основан на повы ш ении активности мозга, и особенно
на сочетании разных ее видов. Доказано, что все факторы, перечисленные
на предыдущей странице, помогают вашему мозгу работать на вас.
Например, исседования показали, что размещение слов вмуте/ж рисунков
(а не в подписях, в основном тексте и т. д.) заставляет мозг анализировать
связи между текстом и графикой, а это приводит к активизации большего
количества нейронов. Больше нейронов = выше вероятность того, что
информация будет сочтена важной и достойной запоминания.
Разговорный стиль тоже важен: обычно люди проявляют больше внимания,
когда они участвуют в разговоре, так как им приходится следить за ходом
беседы и высказывать свое мнение. Причем мозг совершенно не интересует,
что вы «разговариваете» с книгой! С другой стороны, если текст сух
и формален, то мозг чувствует то же, что чувствуете вы на скучной лекции
в роли пассивного участника. Его клонит в сон.
Но рисунки и разговорный стиль —это только начало.

д ал ьш е > 27
как работать с этой книгой

Вот что сделали МЫ 0 >^.ре.деля» к/.а сс. вы о л р е -


Эеляете. £
зсляете. 20мA1е^>^v\0v1cлl^
его
л\акисекдкие^-тежслреЗв- >1, тс/ч«у
точно
ляг('л внешний вид рома.

Мы использовали рисунки, потому что мозг лучше приспособлен для


восприятия графики, чем текста. С точки зрения мозга рисунок стоит
тысячи слов. А когда текст комбинируется с графикой, мы внедряем
текст прямо в рисунки, потому что мозг при этом работает эффективнее.
. Н а о с н с ве о(Ь<ого
т и леждА^ожноло,
Мы используем избыточность: повторяем одно и то же несколько раз, приме­ \ и т ь сколько уг,
\ д о м о в, а !лз о ^ .о г о
^ к л а с с а м ож но »\ол.
няя разные средства передачи информации, обращаемся к разным чувствам —и ск о л ь к о иг, '

все для повышения вероятности того, что материал будет закодирован в не­
скольких областях вашего мозга.
Мы используем концепции и рисунки несколько неож иданным образом, пото­
му что мозг лучше воспринимает новую информацию. Кроме того, рисунки и
идеи обычно имеют эшщитшльное содержант, потому что мозг обращает внима­
ние на биохимию эмоций. То, что заставляет нас чувствовать, лучше запоминает­
ся —будь то гиутка, удивление или интерес.
Мы используем/»озгово/шый стиль, потому что мозг лучше воспринимает инфор­
мацию, когда вы участвуете в разговоре, а не пассивно слушаете лекцию. Это
происходит и при чтении.
В книгу включены многочисленные упражнения, потому что мозг лучше запо­
минает, когда вы работаете самостоятельно. Мы постарались сделать их непро­
стыми, но интересными —то, что предпочитает большинство читателей.
Мы совместили несколько стилей обучения, потому что одни читатели любят по­
шаговые описания, другие стремятся сначала представить «общую картину»,
а третьим хватает фрагмента кода. Независимо от ваших личных предпочтений КЛЮЧЕВЫЕ
полезно видеть несколько вариантов представления одного материала. МОМЕНТЫ
Мы постарались задействовать оба полуишрия вашего мозга; это повышает вероят­
ность усвоения материала. Пока одна сторона мозга работает, другая часто име­
ет возможность отдохнуть; это повышает эффективность обучения в течение
продолжительного времени.
А еще в книгу включены истории и упражнения, отражающие другие точки зре­
ния. Мозг качественнее усваивает информацию, когда ему приходится оцени­
Беседа У камина
вать и выносить суждения.
в книге часто встречаются вопросы, на которые не всегда можно дать простой
ответ, потому что мозг быстрее учится и запоминает, когда ему приходится что-
то делать. Невозможно накачать мышцы, наблюдая за тем, как занимаются дру­
гие. Однако мы позаботились о том, чтобы усилия читателей были приложены
в верном направлении. Вам не придется ломать голову над невразумительными
примерами или разбираться в сложном, перенасыщенном техническим жарго­
ном или слишком лаконичном тексте.
В историях, примерах, на картинках использованы антропоморфные образы.
Ведь вы человек, и ваш мозг уделяет больше внимания людям, а не вещам.

28 введение
введение

Что мо)кете сделать ВЫ, чтобы


заставить сбой мозг поВиноВаться
Мы свое дело сделали. Остальное за вами. Эти советы станут
отправной точкой; прислушайтесь к своему мозгу и определите,
что вам подходит, а что не подходит. Пробуйте новое.
Вырежьте ы прикрепите
НД холодильник.

^ Не торопитесь. Чем больше вы поймете, тем Говорите вслух.


меньше придется запоминать.
Речь активизирует другие участки мозга. Если
Просто читать недостаточно. Когда книга задает вы пытаетесь что-то понять или получше запом­
вам вопрос, не переходите к ответу. Представьте, нить, произнесите вслух. А еще лучше — попро­
что кто-то действительно задает вам вопрос. Чем буйте объяснить кому-нибудь другому. Вы будете
глубже ваш мозг будет мыслить, тем скорее вы быстрее усваивать материал и, возможно, от­
поймете и запомните материал. кроете для себя что-то новое.
Выполняйте упражнения, делайте заметки. Прислушивайтесь к своему мозгу.
Мы включили упражнения в книгу, но выпол­ Следите за тем, когда ваш мозг начинает уста­
нять их за вас не собираемся. И не разглядывайте вать. Если вы начинаете поверхностно воспри­
упражнения. Берите карандаш и пишите. Фи­ нимать материал или забываете только что про­
зические действия во времяучения повышают его читанное —пора сделать перерыв.
эффективность.

Читайте врезки. Чувствуйте!


Это значит: читайте всё. Врежи —часть основного Ваш мозг должен знать, что материал книги
материала! Не пропускайте их. действительно важен. Переживайте за героев
наших историй. Придумывайте собственные
подписи к фотографиям. Поморщиться над не­
^ Не читайте другие книги после этой перед сном. удачной шуткой все равно лучше, чем не почув­
ствовать ничего.
Часть обучения (особенно перенос информации
в долгосрочную память) происходит после того,
как вы откладываете книгу. Ваш мозг не сразу ус- Пишите программы!
ваивает информацию. Если во время обработки
поступит новая информация, часть того, что вы Научиться программировать можно только од­
узнали ранее, может быть потеряна. ним способом: писать код. Именно этим вам
предстоит заняться, читая книгу. Подобные на­
выки лучше всего закрепляются практикой. В
Пейте воду, и побольше. каждой главе вы найдете упражнения. Не пропу­
скайте их. Не бойтесь подсмотреть в решение
Мозг лучше всего работает в условиях высокой задачи, если не знаете, что делать дальше! (Ино­
влажности. Дегидратация (которая может на­ гда можно застрять на элементарном.) Но все
ступить еще до того, как вы почувствуете жажду) равно пытайтесь решать задачи самостоятельно.
снижает когнитивные функции. Пока ваш код не начнет работать, не стоит пере­
ходить к следующим страницам книги.

дал ьш е > 29
как работать с этой книгой

Ч то Вам потребуется
Эта книга написана при помощи Visual C# 2010 Express Edition, работающей с C# 4.0 и .NET Frame­
work 4.0. Именно в этом приложении были сняты все скриншоты, поэтому мы рекомендуем устано­
вить себе именно его. Если у вас установлена Visual Studio 2010 Professional, Premium, Ultimate или Test
Professional-версия, картинки будут отличаться. Где необходимо, это будет оговариваться. Бесплатно ска­
чать версию Express можно с сайта Microsoft.

Настройка VISUAL STUDIO 2010 EXPRESS EDITION --------------------------------------------------

Скачать и установить версию Visual C# 2010 Express довольно легко. Дистрибутив программы находит­
ся здесь:

h t t p : / /w w w .m ic r o s o f t . c o m /e x p r e s s /d o w n lo a d s /

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

IfistaMatkm Options
O Q * ^ IO »-2010

Sefect iht Gp^on^ produst(s) you wouki ice to îTBîsi.' Если y вас уст ановле­
^HiCK»softS<^S«ver2IM »Ex|»«ssSenncePadkl(x«4)(0(W fa(H idStze; 104 на долее старая версия
SQL 5 e w Express integrates nith Visu^ Studio to {ïsvkie b e æ ami
Visual Studio, или .NET
a r v e r - d a tie s c capetàtes. Framework, некоторые
примеры из книги м огут
не сработать.

For итога ігАмтвїйіОп, see ftie-

Скачайте и установите Visual C# 2010 Express Edition. Убедитесь, что установка завершена. На вашем
компьютере окажутся интегрированная среда разработки (которую вам предстоит изучить),
NET Framework 4.0 и другие инструменты.

После установки в меню Start появится новая строка: Microsoft Visual C# 2010 Express Edition. Это
команда для вызова ИСР. Вы полностью готовы к работе.

30 введение
введение

Для наглядного пред­


информация оставления сложит
п о н я т и й б кн м ге
исТользун>тся дыа-
Это учебник, а не справочник. Мы намеренно убрали из книги все, что
грйммс>|- I
могло бы помешать изучению материала, над которым вы работаете. И
при первом чтении книги начинать следует с самого начала, потому что
книга предполагает наличие у читателя определенных знаний и опыта.

У пр аж нени я о б язател ь ны к вы пол нению .


Упражнения и задачи являются частью основного содержания книги,
а не дополнительным материалом. Некоторые помогают запомнить
новую информацию, некоторые —лучше понять ее, а некоторые — на­
учиться применять ее на практике. Необязательными являются только
«Ребусы в бассейне», но следует помнить, что они хорошо развивают ло­ ise rrt
гическое мышление.
В ы полняйте
все упражнения
П о в торени е при м еняется нам еренно. этого раздела-
У книг этой серии есть одна принципиальная особенность: мы хотим,
чтобы вы действительно хорошо усвоили материал. И чтобы вы запом­ Возьми в руку карандаш
нили все, что узнали. Большинство справочников не ставит своей целью
успешное запоминание, но это не справочник, а учебник, поэтому неко­
торые концепции излагаются в книге по несколько раз.

В ы пол няйте все уп раж нени я! Не >^ропускайте эти

Предполагается, что читатели этой книги хотят научиться программи­


хот ит е изучить С*.
ровать на С#. Что им не терпится приступить к написанию кода. И мы
дали им массу возможностей сделать это. В фрагментах, помеченных
значком Ут^ажнение!, демонстрируется пошаговое решение конкретных
К
задач. А вот картинка с кроссовками сигнализирует о необходимости са­
мостоятельного поиска решения. Не бойтесь подглядывать на страницу нение
с ответом! Просто помните, что информация лучше всего усваивается,
когда вы пытаетесь решать задачки без посторонней помощи. А э т и м значком
помечены до­
Код для упражнений из книги можно скачать здесь полнительные
h t t p ; / / w w w .h e a d f ir s t la b s . c o m /b o o k s /h f c s h a r p / упражнения для
любителей логи­
ческих задач.
У п р аж н ен и я «М озгов ой ш турм » не и м ею т ответов.
В некоторых из них правильного ответа вообще нет, в других вы должны
сами решить, насколько правильны ваши ответы (это является частью
процесса обучения). В некоторых упражнениях «Мозговой штурм» при­
водятся подсказки, которые помогут вам найти нужное направление.

д ал ьш е ► 31
обзор команды

Технические рецензенты

!<р,'UC
Лиза Кельнер ^»рроус

Здесь нет ф от огра­


фий Джо Албахари^
Джея Хилярда, Аяма
Синга, Теодоры, Пете­
ра Ричи, Вилла М е-
тельски, Энди Паркера,
Вейна Средни, Дэйва
J\a?!ud Стерлинг Мэрдока, Бриджит-
Жули Ландерс. Особая
Лаладцнс благодарность Джону
Скиту за его предло­
жения по улучшению
первого издания!

Дэвид действи­
тельно нам помог,
показав некоторые,
приемы работы
с ИСР.

При работе над этой книгой мы столкнулись с массой неточностей, вопросов, проблем, опечаток
и даже ужасных математических ошибок. Впрочем... все было не так ужасно, как можно подумать. Но
мы все равно очень благодарны за ту работу, которую выполнили наши технические рецензенты. Кни­
га вышла бы в свет с ошибками (парочка из которых довольно серьезны), если бы у нас не было самой
лучшей на свете команды...

Прежде всего хотелось бы сказать большое спасибо Крису Барроусу и Дэвиду Стерлингу за техни­
ческое сопровождение. Также хотелось бы поблагодарить Лизу Кельнер —это уже шестой обзор, ко­
торый она для нас делает, и именно она сделала конечный продукт настолько читабельным. Спасибо,
Лиза! И особая благодарность Нику Паладине.
Крис Барроус —разработчик компании Microsoft из команды компиляторов С#. Его специализация —
дизайн и реализация различных свойств языка C# 4.0.
Девид Стерлинг работает в команде компиляторов Visual C# последние три года.
Николас Паладине был одним из наиболее ценных специалистов Microsoft, занимавшихся .NET/С # . Он
имеет 13-летний опыт в программировании, особенно в позиционировании технологий Microsoft.

32 введение
введение

Благодарности
Редакторы
Мы хотим поблагодарить наших редакторов Б р е т т а
Маклафлина и Кортни Нэш за работу над этой книгой.
Бретт был автором большинства рассказов, а идея главы 14
принадлежит ему полностью. Спасибо!

Брет т Маклафлин

Кортни Нэш

Команда издателг>ства O’Reilly

Л у —замечательный дизайнер, постигший все секреты своей про­


фессии. Она провела незабываемые часы и сделала для книги
потрясающие графические фрагменты. Если вы видите в книге
нечто фантастическое — благодарите ее (и ее умение работать
с InDesign). Все комиксы являются ее творением. Спасибо огром­
ное, Лу! С тобой потрясающе приятно работать!

В O ’Reilly очень много сотрудников, которых мы хотели бы по­


благодарить, надеемся, что никого не забыли. Особое спасибо
выпускающему редактору Рашель Монаган и индексатору Люси
Хаскинс, Эмили Квил за отменную корректуру, Рону Билодо, кото­
рый не жалел своего времени на экспертные заключения, Сандер­
су Клейнфелду за предложение проверить все еще один раз —всем,
кто помог подготовить эту книгу к печати в рекордно короткие сро­
ки. Мы любим Мэри Треслер и ждем случая поработать с ней снова!
Жмем руку нашим друзьям и редакторам Энди Сраму и Майку Хен­
дриксону. И за то, что вы сейчас читаете эту книгу, нужно поблаго­
дарить лучшую команду рекламистов: Марси Хенон, Сару Пейтон,
Мэри Ротман, Джессику Бойд, Кетрин Барет и остальных сотруд­
ников из города Севастополь, штат Калифорния.
Т
Сандерс Клейнфелд
д ал ьш е > 33
1 =*екш иБ ность с

Визуальные приложения
за 10 минут

Хотите программировать действительно быстро? C # — это


м о щ н ы й я з ы к пр ограм м и ровани я. Благодаря V isu a l S tu d io вам
не потребуется писать непонятный код, чтобы заставить кнопку ра­
ботать. Вместо того чтобы запоминать параметры метода для имени
и для ярлыка кнопки, вы сможете с ф о к у с и р о в а т ь с я на д о ст и ж е­
н ии результ ат а. Звучит зам анчиво? Тогда переверните страницу
и приступим к делу.
с c# это легко

Зачем В ш изучать C #
lACPj или Интегрированная
C# и ИСР Visual Studio облегчают и ускоряют процесс Среда Разработки, --
написания кода. э т о программа для
редактирования кода,
управления файлами
_ , ^ и публикации проектов.
Задачи, которые за бас решает UCP
Чтобы поместить на форму кнопку, вам потре­
v o i d I n i t i a H .e C o m p o n e n tT ,
буются большие куски повторяющегося кода.
th is .SuspSi, |y“ “ , f ■W ndow B . P o rm a. B u tto n () ;
/ / b u tto n l

56) ;
in ,.s i.e „ s , .3 , ,

/ / Pom .1 "'“ ™ '‘^ ' " ’“ “ ‘* l « < t h i a . b u t t o n l _ c l i c k ) , .

‘ s t a t i c claB B p ro g ra m

'/ / S ” S S ’ e n try p o in t f o r th e a p p lic a tio n .


/// < / sum m ary>
S S ’^^f.MainO th is .R e s u m e L a y o u t(fa ls e );
' Wplic.tion.|ngleVi-al|tyl«^^^^

) f

Преимущества Visual Studio u C #


Язык С#, оптимизированный для программиро­
вания в Windows, вместе с Visual Studio позволяет
сфокусироваться на непосредственных задачах.
T ‘ТОЛЬКО личще,
f ‘глядит, но a
^<^'cmpee создается.
'I
i ÿ Your Program ЗЖз
Решения .NET
Framework

Встроенные в С*
j^g-f FrAmeworK
C =3I ИжЛ

How good"’ ©
)Let% get Parted!]

finort © Better # 8ей


i

i/ir p V iS M ^ !
УЛе
Studio с т р и ^ ' 0 - , - .................—
избавляют » f .
0^ рутинное paoom
Aft ritfht! ЬйИКПШ ■■••■■■•*■:

доступ К данным

36 глава 1
эффективность с C#

С#, UCP Visual Studio многое ynpoutaiom


Язык C# и Visual Studio позволят без дополни­
тельных усилий выполнять следующие задачи:

Быстро создавать прилож ения. Программировать на C# очень просто.


Это мощный, легко осваиваемый язык, а Visual Studio позволяет автома­
тизировать большинство процессов.

О Разрабатывать красивы й пользовательский интерд>ейс. Инструмент


Form Designer в Visual Studio превращает создание великолепного поль­
зовательского интерфейса в одну из самых увлекательных задач при раз­
работке приложений на С#. Вам больше не потребуется тратить часы на
написание графических элементов с нуля.

О Создавать базы данны х и взаимодействовать с н и м и . ИСР снабже­


на простым интерфейсом для создания баз данных, которые затем легко
интегрируются в SQL Server Compact Edition и другие популярные при­
ложения.

1окусироваться на реш ении Р Е А Л Ь Н Ы Х проблем . За конечный ре­


зультат работы, разумеется, отвечаете вы и только вы. Но ИСР позволя­
ет концентрироваться на глобальных вещах, взяв на себя:
★ слежение за всеми проектами;
★ упрощенное редактирование кода;
★ отслеживание графики, аудиофайлов, значков и прочих ресурсов;
★ управление базами данных и взаимодействие с ними.
Теперь вместо рутинного написания кода вы можете потратить время на
создание потрясающих программ.
Скоро бы поймет е,
что мы имеем в виду.

дальше > 37
помогите начальнику

11зба6ьте директора о т бумаг


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

Найдите способ
Имя: Laverne Smith быстро перекинуть
эти данные на
Фирма: XYZ Industries ноутбук директора.
Телефон; ( z i z ) s s s - s i z ‘i
Email: LavemeSmith^XyZindustriescoM
Клиент; Yes Поел, звонок: 05/я& /07

“ " Т “", .Г'

..,- 1 -W « * ,

■Muirtiiiiln'ir чш —

38 глава 1
эффективность с С#

Перед началом работы быясните, что именно


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

Директор хочет, чтобы программа работала не толь­


ко на его офисном компьютере, но и на его ноутбуке.
Значит, вам потребуется инсталлятор, который по­
зволит поместить нужные файлы на любой компью­
тер.
Так как приложение должно
работам.^ не молько в офисе,
но и на ноутбуке директора,
без установщика не обойтись.

Перед началом работы


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

дальше ► 39
ваша цель

Ч то мы собираемся сделать
Нам потребуется приложение с графическим интерфейсом
пользователя, объекты, взаимодействующие с базой дан­
ных, собственно база данных и программа установки. Вся эта
огромная с виду работа будет проделана к концу этой главы.
Вот структура нашей будущей программы:

Ве>|
элем еи ^б
упрлбдения.

Визуальные объекты .НЕТ Объекты б»ы данных .N£T | к о „ ,к д а u p d a te |

Команда DELETE ^

ОЭьектВ«'*''

Э т и обьекты являются
элементами управления
адресной книги. 'Ш ^ обгр

\гШ у -
„ „ „ Z I

40 глава 1
эффективность с С#

Готовая программа
поме-щаетсй внутрь
инсталлятора \лЛпйо^5.

Хранилище данных инструм енты Внедрения

.е х е

Ол
б а з а данны х
I Файл
программы

Отде -
лу продаж
'ч останется
4 л >^олько за ~
1л уст ит ь
эт от ин­
сталлятор.

дальше > 41
приступим

Э то Вы делаете 6 Visual Studio


Запустите Visual Studio, если вы еще это не сделали. Пропустите начальную страницу и выберите в меню
File команду New Project. В открывшемся окне диалога New Project выберите тип проекта W indow s Form s
Application, а в текстовое поле Name в нижней части окна введите название проекта Contacts.

....
iSrai^hbsSailedTempiatti
Im t^ T e m p t^ e s
№tdov«sFt»msAf)p<»catK3n Visuet С *
УвиЫС»
А pro^ect fof <feetjng an äpplicebon with »
Windev« Forms user tnteiface
Q a isLibn ry Visual С *

; WPFApplicrtksn \ftsuel С *

! WFBfovwerA4>p»icatk>n Visual C# о С Ш о |= > о Ж Н ь 1


Consol« Application VtsuelC#

; : Empty Project Visu»! С *


В вашей ИСР все может
выглядеть по-другому.
На рисунке показан вид
окна New Project в Visual
Studio 2010 Express Edition.
В Professional или Team
Foundation edition оно мо­
жет выглядеть по-другому.
Но суть его от этого
не меняется.

Команда Save All


А это Visual Studio делает за Вас ■из меню File сохраняет
все открытые файлы,
в момент сохранения проекта ИСР создает файлы F o rm l. c s, в то время как команда
F o rm l. D e s i g n e r . c s и P rogram , cs. Они добавляются в окно Save — только файл,
Solution Explorer и по умолчанию сохраняются в папке Му активный в данный
D o c u m e n ts\V isu a l S tu d io 2 0 1 0 \ P r o j e c t s \ C o n t a c t s \ . момент.
Эт от файл содержит
код, определяющий
поведение формы.
^Од, определяющий
форму и ее объекты.

at

Forml.cs Forml.Deslgner.cs
ßce эт и файлы Visual Studio
создает автоматически.
42 глава 1
эффективность с C#
Возьми в руку карандаш
« .В О З І
Ниже показан возможный вид экрана. Вы должны понимать назначение большинства окон
ч и файлов. Убедитесь в наличии панелей Toolbox и Error List, вызываемых одноименными
командами меню View » Other Windows. В пустые строки впишите назначение каждой части
ИСР, как показано в примере.

Если ваша ИСР выглядит


по-другому, воспользуйтесь Это окно было
^^.^■й^.выбираются командой W indow »R eset увеличено,, чтобы
дать вам больше
работ ы ................. пространства.

дальше > 43
изучи И СР

Возьми в руку карандаш


6Ш6НИ6 Итак, вы описали назначение различных частей ИСР Visual Studio С#.
Здесь вы можете сравнить написанное с правильными вариантами
ответа.
Здесь выдираются

ЗЭесь собраны
визуальные
элементы
управления, ^
которые \ ®
можно
перетащить
на форму.
здесь
\^оказаны
свойства
выбранного
эдеменилд
управления
суормы-

В окне E rror List Щ ел чок на этой


отображаются
вкравшиеся в коо кнопке вклю чает
оилибки. и отклю чает
ф ункци ю
ав то м атического
сворачивания
окна. У панели
Toolbox она
вклю чена
Form i.cs и по ум олчанию .
•появляются

44 глава 1
эффективность с C#

_ Часзцо
ЧадаБаеМые
Б оЦ Р о Сь !

Если код создается автоматически, я загрузил и установил бесплат­ Окно ИСР отличается от показан­
не сводится ли изучение C# к изучению ную версию Visual Studio Express. ного на картинке в книге. Что делать?
функциональности ИСР? Достаточно ли этого для выполнения
упражнений из данной книги или мне ; Для перехода к настройкам по умол­
I Нет. ИСР поможет вам в выборе
потребуется купить другую версию чанию выберите команду Reset Window
начальных точек или измении свойств
приложения? Layout в меню Window, затем восполь­
элементов управления форм, но понять, зуйтесь командами меню View » Other
какую работу должна выполнять про­ ! Все упражнения из этой книги вы­ Windows, чтобы открыть недостающие
грамма и как достичь поставленной цели, полняются в бесплатной версии Visual окна.
можете только вы. Studio (которую можно получить на сайте
Microsoft). Различия между версиями
Express, Professional и Team Foundation
Я создал новый проект, но не никак не повлияют на процесс написания
нашел его в папке Projects, вложенной
в папку Му Documents. Почему?
профамм на C# и создания полнофункцио­
нальных приложений.
Visual Studio
Q ; Новые проекты Visual Studio 2010 генерирует код,
Express помещает в папку L o c a l
Mojy ли я переименовывать фай­
S e ttin g s \A p p lic a tio n
D a t a \ T e m p o r a r y P r o j e c t s . При
лы, созданный ИСР?
который можно
первом сохранении вам предлагается Q ; Конечно. Новому проекту ИСР
задать новое имя и поместить в папку по умолчанию присваивает имя F o r m l использовать
Му D o c u m e n t s \ V i s u a l S t u d i o (F o r m l. c s , F o r m l. D e s i g n e r . c s
2 0 l 0 \ P r o j e c t s . При открытии нового
проекта или закрытии временного, вам
и F o r m l . r e s x ) . Ho его можно поменять
в окне Solution Explorer. По умолчанию как основу для
предлагается сохранить или удалить имена файлов совпадают с именем
последний. (ПРИМЕЧАНИЕ: Отличные формы. Как можно видеть в окне Properties,
их изменение не влияет на имя формы.
программы.
от Express версии Visual Studio не ис­
пользуют папку временных проектов, Последнее меняется изменением поля
а помещают файлы непосредственно (Name) в окне Properties. Имя файла при
в папку Projects!) этом остается тем же.
Но только вы
Для файлов, форм (и других частей про­
Что делать с ненужным кодом,
автоматически созданным ИСР?
граммы) можно выбирать произвольные
имена. Выбор значимых имен облегчает
отвечаете за
работу с программой, но об этом пока
; Его можно отредактировать. Если можно не думать. корректную работу
по умолчанию создан не тот код, который
вам требуется, достаточно внести в него
необходимые изменения — вручную или
это11 программы.
средствами пользовательского интерфей­
са ИСР.

дальше > 45
лучше один раз увидеть

Создаем пользовательский интерфейс


Добавление элементов управления в ИСР Visual Studio
осуществляется методом Drag&Drop (перетащить и бро­
сить). Рассмотрим процесс добавления логотипа к форме:

Q Э лем ент управления PictureB ox.


Перетащите на форму элемент управления PictureBox
из окна Toolbox. ИСР при этом добавит в файл
F o rm l. D e s i g n e r . c s код нового изображения.

Чтобы увидеть ^ ^ Start Рзд


список инстру­ & All W indows Forms
ментов, наведите л C om m on Controfs
указатель мыши Pointer
на слово Toolbox @ Button
в верхнем левом S Checkeox
углу ИСР. Если §3 CheckedLtstBox
оно отсутствует, Э ComboBox
выберите команду DateTtmePjcfcer
Toolbox в меню A Labet
View. A ImkLabel
51 ListBox
ListVtew
Й M askedlextBox
^ M onthC stendar
Tt! Notr^kon

^ PictureBox —

l‘' W ¥ \ \ .
0 RaAfcbt\toi
RkhTextBox
Щ. TextBox

0 файле Forml.Designer.es.

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

Forml.Designer.cs О разработке интерфейсов мы поговорим позднее. На данном


этапе сосредоточьтесь на поведении создаваемых элементов
управления.

46 глава 1
эффективность с C#

Визуальные Kj}3KI]AU^e Иншрумейгпы


объекты данных
.NET

здесь

Режим Zoom для элем ента P ictureB ox.


О Доступ к свойствам элемента управления осу­
ществляется щелчком на маленькой черной
стрелке. Для свойства Size элемента PictureBox
выберите тип Zoom: (Дедчок на
м аленькой
С Pormi шш
Задать разАА&р S P « г»'“
эл ем ен та @ W i e r ^ 1r«d«s 9 o c m y i^ /
можно б окне свойст оам
I Choose Im sge. эл е м е н т а
prope-rtie-s-
Щелчок управления.
Size M o d e
на черной
Dock in Par
стр ел ке datm
бы ст рш
доступ к общим
свойствам
элементов.

Щелчок на строчке Choose Imaa^

e Зогрузка л о го ти п а фирмы по производству б у м аги .


Архив с логотипом находится на сайте ( h t t p ; / /w w w . h e a d f I r s t l a b s . c o m / b o o k s / h f c s h a r p /
H F C s h a r p _ g r a p h i c s _ c h 0 1 .z i p ) . Сохраните его на жестком диске своего компьютера. Щел­
кните на черной стрелке элемента PictureBox и выберите в появившемся меню команду Choose
Image. Откроется окно диалога Select Resources. Установите переключатель в положение Local
Resource и щелкните на кнопке Import... Остается только указать путь к файлу с картинкой.

дальше > 47
экономим ресурсы

Visual Studio, за сценой



Кажое ваше действие Visual Studio сопровождается написанием
кода. В момент загрузки логотипа Visual Studio создала ресурс
и связала его с вашим приложением. Ресурсом называется лю­
бой графический или звуковой файл, значок или другие данные, Q -
подгружаемые к приложению. Логотип интегрировался в про­
грамму, и при открытии на другом компьютере элемент управле­
ния PictureBox сможет его использовать.
В момент перетаскивания элемента управления PictureBox на
форму для хранения данного ресурса и его связи с проектом ав­
Логотип стал
/
томатически был создан файл F o rm l. r e s x . Двойной щелчок на
ресурсом приложения
имени этого файла позволит увидеть импортированное изобра­ Contact List.
жение.

S o lu tr o n Explorer в окне Solution Explorer щелкните на квадратике


со знаком «плюс» слева от имени файла F o rm l. cs.
Это откроет доступ к файлам: Form l .D e s ig n e r , c s
Solution 'C on ta cts' CI project) и F o r m l.r e s x . Дважды щелкните на файле F orm l.
d C m te c te r e s x , затем на стрелке рядом со словом Strings и вы­
берите в меню вариант Images (или нажмите Ctrl-2),
|> i l i Properties
чтобы увидеть импортированный логотип.
b 9 References
Л Ц ] F o rm l.cs
^ Form l.Designer.es Вторая кнопка
Form l.resx X I
Im port в окне
Form l.resc* Select Resource
i ü Im ages » J| A d d Resource
Program .cs помещает
логот ип в папку
Resources окна
Solution Explorer.
Чтобы исправить
ситуацию,
установите
переключатель
Local Resource
и повторно
импорт ируйт е
файл.

Этот файл ИСР


эт о
создала при импорте
созЗанные - изображения. Сюда
рйНйв'
помещаются любые
Forml.resx ресурсы, связанные
Program.cs
с формой.

48 глава 1
эффективность с C#

Редактирование кода
Иногда в автоматически созданный код требуется внести из­
менения. Рассмотрим эту процедуру на примере добавления
к логотипу всплывающего текста.
При редактировании формы двойной щелчок на любом эле­
менте управления автоматически добавляет в проект код.
Дважды щелкните на фрейме PictureBox и вы увидите код, ко­
торый выполняется при каждом щелчке на данном элементе
управления. Этот код должен выглядеть примерно так:

p u b lic p a r t ia l c la s s F orm l : F orm


{
p u b lic F o r m l {)
при каждом щелчке
пользователя на логотипе.
I n itia liz e C o m p o n e n tO ;
1 Название метода
^ , п о к а з ы б а ^ ^ 1^ л ч к о М
p r iv a te v o id p ic tu r e B o x l_ C lic k (o b je c t sen d er, E v e n tA r g s e) ^ а п у с к а е т ^ ^ ^ p ic tu r e B o X .
---- ------------------. на
U/2 элементе
{
M e ssa g e B o x .S h o w ("C o n ta o t L i s t 1 . 0 . \ n W r i t t e n bys Zour Name". "A b o u t");

}
Введите эт от код Пи введя код, щелкните
V
После двойного щелчка на кнопке Save панели
инструментов ИСР
на элементе РкЫгеВок выберите команду Save
курсор окажется
здесь. При вводе в меню File.
кода игнорируйте
всплывающие окна.
Ч асзц о

^аД аБаеМ ы е

Что такое метод? Зачем нужен символ \п ?

О ! Методом называется именованный блок


кода. Более подробную информацию вы по­
О ! Это знак переноса строки. Он показыва­
ет, что Contact List 1.0 будет написан на стро­
лучите в главе 2. ке, а Written by: записывается с новой строки.

дальше k 49
запуск приложения (наконец-то!)

Пербый запуск прило)кения


Нажмите кнопку F5 или щелкните на кнопке с зеленой
стрелкой I (^ ) на панели инструментов, чтобы про­
тестировать результат своей работы. (Это называется
«отладкой», то есть запуском программы в ИСР.) Для
остановки процесса выберите Stop Debugging в меню
Debug или щелкните на кнопш j на панели инстру­ Все три кнопки
ментов. работают, и вам
не ^^отребовало,^
сг, ; IS : а J^ucamb для этого код.

About
Щелчок на логотипе
вызывает только
что созданное окно
C o n tact List 1,0. About.
W ritten b f. Your N am e

OK

_ Часвдо

--------- ^ а Д а В а е М ы е ------------
Где )ke Mou файлы? B onj=*oc:bi
П ри запуске программы Visual в моей ИСР кнопка с зеленой стрелкой
Studio копирует файлы в папку С* превращает называется Debug (Начать отладку). Она
Му D o c u m e n ts \V is u a l S t u d io вашу программу запустит программу?
20 1 0 \P ro je c ts \C o n ta c ts \ в исполняемый
айл, находящийся
C o n t a c t s \ b i n \ d e b u g . Дважды щелк-
ните на созданном ИСР файле .ехе, Г папке debug. • Конечно. Щелчок на ней приведет к вы­
полнению программы внутри ИСР, что в дан­

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

с»
Я не вижу на панели инструментов
сй 1=orm1 Ш] кнопку Stop Debugging. Что делать?
Designer.cs шти
Form1.cs Forml.resx Properties
Q l Эта кнопка появляется только при запу­
Это не ошибка. Существуют два щенной на выполнение программе. Запустите
уровня папок, файлы с кодом С # приложение, и вы увидите, как она появится.
находятся во внутренних папках.

50 глава 1
эффективность с C#

Bom что у)ке сделано


Итак, мы создали форму и объект PictureBox, щелчок на ко­
тором вызывает диалоговое окно с текстом. Теперь нужно
добавить поля с информацией; имена и телефоны из списка
контактов.
Эту информацию мы сохраним в базе данных. Visual Studio со­
единит с ней поля, то есть нам не потребуется вручную писать
код для доступа к этой базе. Сейчас мы займемся ее написани­
ем, то есть перейдем от раздела Визуальные объекты .NET пря­
мо к разделу Запись данных.

Визуальные
объекты .NET
Объекты Хранилище иис1л|»умеиты
в)<ез{^ения

П оэтому снячйЛй
Мы не можем нцжно написать
соединить форму базу Wзаполнить
с базой данных, так ее данными.
как база данных пока
от сут ст вует .
Э т о мы уже
сделали... которое УД

с 9анн1?|Мм м3 олз

Visual Studio автоматически сгенерирует для вас код,


соединяющи!! форму С базой данных, но СНАЧАЛА
нужно создать саму базу.
дальше ► 51
сохраните, чтобы потом использовать

Для хранения информации ну>кна база данных


Код, связывающий форму с данными ИСР, гене­
рируется автоматически, так что нам нужно все­ УЗеЗцилесь, иило
го лишь:

О Добавить к проекту базу данны х S Q L .


В окне Solution Explorer щелкните правой
кнопкой мыши на проекте Contacts, выбе­
рите команду A d d » N ew Item. В открывшемся Э т о ф айл SQ L
нашей новой
окне выделите строчку Local database, а в поле базы данных-
Name укажите имя файла ContactDB.sdf.
ContactDB.sdf
AebSNew№
em-C&ftacts ТШШ

SetBigsR Tfpt: Vbu»IC* Herns

Выбрав Local ResouKUFite VeoalC#Bemi


Database,
вы созда­ ё etFile
T V'«uatC#Kems
дите файл Interfec* Vi«ualC»items
SQ L Server Vt5ue!C«Rems
Compact Й Cod«F><« VutulC*(terns файле»! базы
Edition, в ко­ Oess Visua«C«tte<T.s данных SQL
тором и будет
3 W fndowsForm S e r v e r C o p v ip a c t
храниться E d itio n и м е ю т
наша база. & Det«Set Visu*JC*hemi расш ирение SUi'-
About8ox VoulC«Items
■й-
-Э"
, rtsuatOfltenjs -
Visual C * hems

0 Щ елкните на кнопке Add в ни ж ней части


окна A dd N ew It e m .

О З акройте м астер D a ta Source C onfiguration.


Рудыпе
Щ елкните на кнопке Cancel, так как в данный
момент мы не будем останавливаться на конфи­ оС Ш ор»оЖ Н ь1
гурации источника данных.
В версиях приложения, отличных от
Express, вместо окна Database Explorer
Q П о см о тр и те на полученны й результат. фигурирует окно Server Explorer
В списке файлов окна Solution Explorer должен Окно Server Explorer в версиях
появиться файл ContactDB.sdf. Дважды щелкни­ Professional и Team Foundation editions
те на его имени и посмотрите на левую часть сохранив всю функциональность окна
экрана. Вместо окна Toolbox там окно Database Database Explorer, позволяет просматри­
Explorer. вать сетевые данные.

52 глава 1
эффективность с C#

Визуальные Объекты ХранцАище инструменты


База данных, созданная UCP бнвзрвнця

База данных SQL — это способ систематизиро­


ванного хранения информации. ИСР дает вам Uv
все инструменты для управления как данными,
так и самой базой.
Данные в базе хранятся в виде таблиц. Столбцы
разделяют данные по категориям (например,
«имя» или «номер телефона»), а строки содержат
информацию о каждом контакте.

База SQL содержит


оаши данные,
информацию о5 их
ст рукт уре и код
доступа к ним.
Вами Злин^!е
хранятся 6 виде
Эикаммиеском
илаблице'- процедуры

Язык SQ L
SQL расшифровывается как Structured Query
Language —язык структурированных запросов.
Этот файл содержит базу
Он предназначен для доступа к данным в базах SQL. Именно 3dect> будут
и имеет собственный синтаксис и структуру. Код сохранены наши таблицы
SQL представлен в виде операторов (statements) SQ L и данные.
и запросов (queries), а также хранимых проце­
дур (stored procedures). ИСР генерирует за вас
операторы SQL и хранимые процедуры, позво­ ContactDB.sdf
ляя создаваемому вами приложению осущест­
влять доступ к данным базы.

дальше ► 53
хранить данные легко

Создание таблицы для списка контактов


Теперь базу нужно наполнить данными. Обычно использу­
ется представление в виде таблицы, поэтому сначала соз­ Ч асто

дадим таблицу People, в которую и поместим контактную ,аДаБаеМые


информацию: B o lïp o C jjI

• Что же такое столбец?


Д обавление таблицы
Щелкните правой кнопкой мыши на строчке Q * Столбец — это одно из полей та­
Tables в окне Database Explorer и выберите ко­ блицы. В таблице People можно создать
манду Create Table. столбцы FirstName и LastName, относящи­
еся к типу String или Date или Bool.
Database Exptorer - X

• Зачем нам столбец Соп1ас1Ю?


Dffta Connections
M ySj ContactDB.sdf
^ ! Он позволит присвоить уникальный
i> ______,___ номер каждой записи в таблицах базы. Так
!> iJJ R- Create Table как мы сохраняем контактные данные от­
New Query дельных людей, имеет смысл их пронуме­
ровать.
i^ Refresh
i S Properties Alt+Enter

Что такое тип данных Int?


T
Теперь к таблице нужно добавить столбцы. Нач­
Ql Int — это сокращенние от Integer
(целое число). То есть в столбце ContactID
нем со столбца ContactID, чтобы присвоить каж­ могут содержаться только целые числа.
дому контакту уникальный номер.

Информации слишком много, дол­


О Создание столбца C o n ta c tID
жен ли я во всем этом разбираться?
Введите в поле Column Name название
ContactID, а в раскрываюш;емся списке Data
^ ! Ничего страшного, если на данном
Туре выберите вариант Int. В списке Allow Nulls
этапе что-то остается непонятным. Пока
должен быть выбран вариант No.
что ваша основная задача — получение
В списке Primary Key выберите вариант Yes. То навыков работы с ИСР Visual Studio. До­
есть именно это поле будет использоваться в ка­ статочно научиться подготавливать фор­
мы и запускать программу (Если же вы
честве уникального идентификатора записи.
хотите узнать больше о базах данных, по­
читайте, например, книгу «Изучаем SQL».
I Column Name Data Type Nüils Unique Primary
ContactiD Yes
Ji8L

T
А о б а в ^ е столбец ContactID с т ипом данных int. В списке Allow Nulls
М е р и т е вариант No, а в списках Unique и Primary Key вариант Yes.

54 глава 1
эффективность с C#

Визу»л11ные Объекты Храимлище 1!яетрумвншы


объекты 6«Ь1 jasBWx данных Внез(;ения
■NET .NET

О Генерация идентиф икационны х номеров


Информация в столбце ContactID будет использо­
ваться только базой данных, нам она не требует­
ся, ее имеет смысл генерировать автоматически.
I
В окне свойств присвойте свойству Identity зна­
чение True, чтобы сделать столбец ContactID
идентификатором для всей таблицы. ^ Ь 1 здесь
В поле Name в верхней части окна введите зна­
чение People.

в о кк. з о г « " «
U

с ■3 E^i^tTriЯe-^*eop^e

ш
Generei
iJ Rdresh
Istame
ColumnName
М
е}р
Peopie
Datatype length AllowNutts Uniqu« PrtmaryKey
Первичный ключ
является ун и ­
кальным иден­
тификатором
записи, поэтому
4 Mo Yes ¥e он обязательно
должен быть за ­
дан.

1
Ы«-
MicfosoftSQLServerCompact
ContactD6.sdf
Det^Vah«'............
is WmisiffisdsniKOEHtiss Ddaultvafoefor^iiscoSumrv.
добавлении
»овои записи поле
OK Cftncet ^о>л^лсИО будет
обновляться
‘^°<^0Алатически.
8 раскрывающемся списке справа от поля
Identity нужно указат ь значение True,
чтобы сделать столдец Contact!Р
идентификатором записей таблицы.

дальше ► 55
оформим в таблицу

Поля 6 контактной карте — это


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

р е о р '®
Имя: Laverne Smith p.«.
Фирма: XYZ Industries
Телефон: ( z i z ) s s s ~ s x z ‘i
Email; Laverne.Smith@XyZindustries.com
Клиент: Yes Поел, звонок: o s /z & /o i

JLJI
о каждом человеке мы

^оследтго звонт ^'''^'^^

ШТУРМ
Какие проблемы могут возникнуть, если одному
человеку сопоставить несколько записей?

56 глава 1
эффективность с C#

КТ9 И Н Т<ЛеЛ#^Т?
Таблица People готова и для нее уже задан первичный ключ, осталось добавить столбцы для всех
полей с данными. Укажите, к каком типу должны принадлежать данные, и выберите для них вер­
ное описание.

Н азван и е стол бц а Тип дан н ы х О п и сан и е

Последний звонок mt Дата и время

Имя Lit Логический тип


true/false

Идентификатор nVarcliarQQQ) Строка из букв, цифр


и других символов
максимальной длиной
100 знаков

Является ли Jateti:лае Целое число


клиентом?

дальше * 57
это именно мой тип

КТО
Проверьте, правильно ли вы сопоставили типы данных и описания таблицы People.

Название столбца Тип данных Описание

58 глава 1
эффективность с C#

Ввзуальямв Объекты хранилище инструменты


Забершение таблицы объекты 6»зь15«в»ых данных Зне^рения
.NET .NET
...
По аналогии со столбцом ContactID добавьте Г.
еще пять столбцов. Вот как должно выглядеть
окно Edit Table после завершения работы: XV 0
])ы здесь

, Если
, парамет р
i Allow Nulls
имеет
' значение
NOj столбец
не может
оставаться
•пустым.
Поля типа
Bit при -
нимают
значения True ^^ф орм ация
или False и о клиенте
м огут быть может, быть
предст ав­ , неполной,
лены в виде .^ о э т о м у
переключа - o f io u p a c M
теля. значение Yes
Щ елкните на кнопке ОК для сохранения таблицы. Она будет добавлена к ва­
шей базе данных.

ЕМ.?»« •

Щелчок на кнопке^
ОК добавит
таблиц!^ People реор'в
к базе Эанных.

Новая таблица пот


дАя вв% 7 д а н н ь !Т ° ^ "

дальше ► 59
добавляем данные

Перенос 6 базу данных с карточек


Все готово для ввода данных в базу. Для начала
возьмем шесть карточек с контактной информа­
цией от вашего босса. Нужно внести
D atabase Estploret - X
данные с этих
илести карточек
s [ p Data C o n n ec tio n s в таблицу People.
j ContectD B .s(if
Л l J T ables
■ Peop‘-
Ф Щ елкните на квадратике со зна­ h 1 л P.ephcati Drop Tabte
ком «плюс» слева от строчки Table Properties
Tables в окне Database Explorer ttfit Table Schem#
(или Server Explorer), затем NevSfQueiy
щелкните правой кнопкой мыши Q- S how T able Data j
на имени таблицы People и вы­
! Copy Ctrl-i-C
берите команду Show Table Data
Rrfrah
в появившемся меню.
Properties Ait+Er.ter

В центральном окне появится Имя: Ыг Nelson


сетка таблицы, куда нужно вве­
сти данные с карточек. (Изна­ Фирма: JTP
чально во всех ячейках стоит телефон: (40--^)?^^-^^
значение null, введите вместо Erna«-. L.feMelsoneJTP.ORa
него свою информацию.) Стол­
бец ContactID будет заполнен ЗН»' Клиент;
автоматически.

Имя: Luanda Ericson О Paper свич>в(^

Фирма: Ericson Events


Имя: L lo y d J o n e s
Телефон; ( 2 .iz ) s s s - ^ s z s
Фирма: Black Box Inc.
Email: LucySEricsonEvents.info
Телефон: (7 iS )S S S -S & 3 8
Клиент: No Поел, звонок: £35/17/10
Email: LJones@Xblackboxmc-com
Клиент: Yes Поел, звонок: o s /z & /to

60 глава 1
эффективность с C#

Имя: Sarak Kalter ^


Имя: Matt Franks. ( Фирма: Kalter. Riddle and Stoft
Фирма: XYZ Industries Телефон: (6 3 -4 )5 5 5 --5 6 4 1 .
Телефон: (Z X Z )S S S -8 i-Z S Email: Sarah^KRS.org
Email: Matt.Franks&XyZindustries.com Клиент: No Поел, звонок: i z / i o / o s
1Слиент: Yes Поел, звонок: 0 5 /2 6 /1 0

1мя: Laverne Smth.


Фирма находится в США, Фирма: XYZ Industries
поэтому директор записывает
даты как 0 S /Z & /1 0 , что Телефон; ( z i - z ) s s s - s i z ^
означает 2.6 мая ЯОЮ. Вы
можете вводить их в другом Email: Laverne.Smith@XyZindustries.com
формате.
Клиент: Yes Поел, звонок: 04 / 1 1 /1 0

^ После ввода всех данных .


снова выберите в меню File с Г
команду Save All. Записи будут Команда Save Al! сохраняет бее
сохранены в базе данных. открытые файлы, а команда Save
Z Z k o файл, над которым вы
сейчас работаете.

Частно
Л аД аБаеМ ы е
БоЛ роС ь!

Б: Куда попадают введеные мной данные? Становятся ли введенные записи частью моей про­
граммы?
грам
О ; ИСР автоматически сохраняет данные в таблице People
вашей базы данных. При этом таблица, ее столбцы, типы 0: Да, данные — такая же часть программы, как код или
данных и сами данные хранятся в файле ContactDB.sdf, кото­ созданные формы. Файл ContactDB.sdf копируется и хранит­
рый является частью вашего проекта, поэтому ИСР автомати­ ся вместе с исполняемым файлом. Для доступа к данным
чески обновляет его при внесении любых изменений. приложение читает файл ContactDB.sdf и вносит в него новые
записи.

^ в«™ S<?L .____

3
ContaetDB.sdf

дальше k 61
все данные в одном месте

источник данных соединит форму с базой


Все готово для создания объекта базы данных .NET, который будет использовать для взаимодействия
с базой. Нам потребуется источник данных. Он представляет собой всего лишь набор операторов SQL,
при помощи которых ваша программа будет обращаться к базе ContactDB

Завершив ввод данных,


О Возвращение к ф орм е. ^
Закройте таблицу People и схему базы данных ContactDB к форме.
для возвращения на вкладку Form l.cs [Design].

People Query(OW...cts\ContactDB.sdf)^X j
ContactID Name Company Telephone Email Client LasCail
1 Lloyd Jones Black Box Inc. (Л8)555-5638 Uones@xbtack.„ True 5/26/201012:00..
2 Lucinda Ericson Ericson Events C212)555-9523 lucy@ericsonev... False 5 Л 7 /Ж 0 12:00..
3 Liz Nelson JTP (419)555-2578 liznelson@JTP.... True 3/4/200S12;00:...
4 Matt Franks XYZ Industries (Л2}555-8125 M8tt.Franks@x... True 5/26/201012:00..
5 Sarah Kalter Kalter, Riddle a„ (614)555-5641 sarah@krs.,org False 12,^0/200812:0..
§ Laverne Smith X¥Z Industries (22)555-8129 Laverne.Smith... True 4/ll/201012iOO..
NULL NULL NULL NULL NULL NULL

О Д обавление к при л ож ени ю нового источника данны х.


Выберите в меню Data команду Add New Data Source.

Создаваемый исмочник
данных будет отвечать
за все взаимодействия
формы с базой.
3

62 глава 1
эффективность с C#

Визуальные Объекты Хранилище Инетруменшы


объекты данных данных ЗН1§^еНЦЯ
-NET „.NET

к л

О Конф игурация нового источника данны х


Теперь нужно указать параметры взаимодействия источни­
ка данных с базой ContactDB. Вот как это сделать: 1ы здесь
★ В поле Data Source Type выберите вариант Database
и щелкните на кнопке Next.
★ В поле Database Model выберите вариант Dataset
и щелкните на кнопке Next.
★ Раскрывающийся список Choose Your Data
Connection содержит только один вариант, соответ­ ТйКйМ способом вы со-
ствующий вашей базе Contact. Щ елкните на кнопке
Next. Л л People
& базе данных ContactDB.
★ В поле Choose Your Database Objects установите
флажок Tables.
Express, предлагается
Убедитесь, что в поле Dataset Name введено значе­ сохранить строки под­
ние ContactDBDataSet и щелкните на кнопке Finish. ключения в ф 1йлТкТн -
^Р’^^ожения.
^т о е т ьт е «Yes».

Form!
- взаимодействия с базой ContactPB-

A bout "► C ontactD B D ataS et.xsd

C ontact List 1.0.


W ritten byi Vour N am e C ontactD B .sd f

OK
Файл с базой
C ontactD B D ataS et. данных.
1L Это ваша
D esigner.cs

форма. Эти файлы созданы


данных, параметры которого вы
только что выдрали.

дальше > 63
соединим все вместе

Добабление элементов, обязанных с базой данных


Добавим на форму другие элементы управления. Все они
должны быть связаны с базой данных и со столбцами табли­ Мы возвращаемся к созданию
цы People. объектов формы, которые
будут взаимодействовать
То есть изменение данных в любом элементе управления с хранилищем данных.
формы должно отображаться в соответствующем столбце
таблицы.
Если вы не видите эту
вкладку, 6 меню Pata
Выбор источника данны х. выберите команду
Show Pata Sources.
В меню Data выберите команду Show Data Sources. От­
кроется окно Data Sources с перечнем настроенных
источников данных.

I
Database Exptorer Можно щелкнуть
на корешке
вкладки Data
Sources, распо­
ложенном внизу
окна Database
Explore.

О Вы деление таблицы People.


Под пунктом ContactDBDataSet вы увидите таблицу People со всеми столбцами. Если выделить
строчку People в окне Data Sources и затем перетащить мышью на форму, автоматически по­
явится еще один элемент, при помощи которого можно просматривать и вводить данные. По
умолчанию это будет DataGridView, то есть еще одна таблица. Щ елкните на расположенной
слева от имени таблицы People и выберите команду Details, чтобы получить возможность до­
бавлять индивидуальные элементы управления для каждого столбца.

D ata S o u rc e s - Д X Щ елкните нй стрелке


::
и выберите в меню команоу
л [дЗ C o n ta ctD B D ataS etl
PetlЯ^(sJ чтобы добавить
к форме несколько разных
- ^
элементов управления.
1|Ы| C o n ta ctID

С И N am e
Jgii C o m p a n y

Здесь должны Q T e le p h o n e

быть показаны jabi! Em ail

все созданные 0 C lien t


столбцы. LastCatt

64 глава 1
эффективность с C#

Bu3ys«Mbie О бъекты Храаидище ингт^умені


объекты б н ы данных данных Вне;{»»іія
.NET .NET l= = l

- cS

Щ ^ в щ

здесь

о Создание элементов управления связанных с таб л и ц ей People


Перетащите таблицу People на форму. Появятся элементы управле­
ния, соответствующие столбцам базы данных. Волноваться о том, как
именно они выглядят, пока не нужно, важно, чтобы они просто по­
явились.
Для перевода формы в активное состояние, достаточно
перейти на вкладку Forml .cs [Design] или открыть файл
Form l. es из окна Solution Explorer.
Э т у панель
управления
Зля навигации
по таблице
создала ИСР- Элементы
управления,
созданные
после
перескивания
3таблицы
0)шрапу: People нл
Тв1е«йэсяте:
форму.
ВШ:
Э т и ком понента dent: IdieckB oxI
не видны на самой
форме, они AUUAt? Ы яМ ; Thuredäy . December 24,2(ЮЗ
Этот адаптер
указывают на коо, отвечает
который 5ыл за взаимодействие
создан ИСР для —ч с командами SQL.
взаимодействия / ^ äcortSKtDBDaföSeÜ peepteBirntingSource ■^ 'p e o p ie T a H e ftd sp te -

с таблицей People ^ ta b le A ita p le f M s n s s e r .i! ^ !J*peo(ilei(«äin 3 l« » ig ato f


и базой данных
ContactPB-

Этот объект
соединяет форму
с і^адлицеи People.
^лнель

дальше ► 65
сделаем красиво

Хорошие программы понятны интуитибно


Имя: taveme Smith
Теперь наша форма работает. Но при этом она Фирма: XYZ Industries
имеет не самый презентабельный вид, а ведь при­ форма с т а ­
н е т 5олее ^o m ф o н :(z^z)sss-8 tzя
ложение желательно делать не только функцио­
нальным. Им должно быть приятно пользоваться. понятной, Email: Laverne.Smith@XijZindustries.com
Сделаем его похожим на карточки, с которых мы если п р и ­ Клиент: Yes Поел, звонок: 0S/Z&/07
дать ей вот
переписывали контактную информацию. такой вид.
Ж
Выравнивание п о л е й и и х названий.
Выровняем поля и их названия по левому краю фор­
мы. В таком виде ею будет удобней пользоваться.

•i* Forml
И << О

Cratad ID:
П ш леретаскибйнмы N«ne:
эм м ент ов управления
бцдцт появляться Согаржиу:

линии синего цвета, Td^hone;


упрощающие процедуру
выравнивания.
-fflo
Cfer*; Cjl chsckSratl 6
о .......... ... -jQ
Thunsday , Decenrt>er 24.2009

Уд ал ени е п од пи си к q)лaж кy C lient.


После перетаскивания на форму флажка Client справа
от него оказалась ненужная подпись. В окне Properties,
расположенном под окном Solution Explorer найдите
свойство Text и удалите слово checkboxl.
Properties ' a X Для удаления м е т к и
cKentCheckBox System.Wmdows.Porms..Check » очистите это поле.
• )1 .
TsbStop True

{cbedcBoxl 4 m _
TextAlign Middieleft
TexUmageRetation Overiay
ThreeState False
UseCompetibteTect( Fat»
UseMnemonk True
UseVtsualStyleBeckC Tnie
UseWaitCursoF FaEse
___ iOsible--___ ____ Тше_ ............
Tert
The text associated with the cofrtiel

66 глава 1
эффективность с C#

В и зуиьны е О бъекты Х^вшище иист(»умвктьг


объекты 6вЬ1 gsHHW* данных
.NET .NET

^Ь 1 здесь

@ П р и д ан и е процзессионального вида.
Щелкните в произвольном месте формы в окне Properties При раскрытии формы
и найдите свойство Text. Введите в это поле название на полный экран положение
Objectville Paper Company Contact List. элементов управления
не меняется, форма
Присвоив свойствам MaximizeBox и MinimizeBox знау выглядит некрасиво.
чение False, можно убрать возможность разворачивать Поэтому мы просто
и сворачивать форму. уберем эт у возможность.

Propertws
F orm l Sy5tem.Windows.Fortns.Form

........:
^owbTaskbar True
должно „одд p- Size 408, 261 Свойство Text
SizeGripS'^te Auto
StartPositior» WindowsDefauttlocati.
задает название
Tag
формы.

Если окно Properties отсутствует, выберите


одноименную команду в меню View.

Хорошим считается приложение, с которым


легко работать. Его функциональность должна
соответствовать ожиданиям среднестатистического
пользователя.
дальше > 67
напоследок

Тестирование
Осталось запустить программу и убедиться, что она работа­
ет правильно! Вы уже знаете, как это сделать, поэтому про­
сто нажмите F5 или щелкните на кнопке с зеленой стрелкой
на панели инструментов (также можно выбрать команду
Run из меню Debug).
Запускать можно даже не полностью готовые программы.
Если в коде ИСР есть ошибки, программа не запустится.
Objectville Paper Company Contact List

И < n У a
Э т и элем енты
у прав л е н и я
Contad 10: 0
Переходить от одной Name: Lloyd Jones
записи базы к Эругом.
Смтрапу: 0ad< Bax inc.

Tel^hone: (7181555-Ж8
Компиляция БпаЙ; LJones@xbiad<bo3dnc.com

профаммы (Sent:
UrtM: Wednesday. May 26,2Й10
переписывает
данные в базе.
Этот аспект
будет подробно
рассмотрен
в следующей главе
РР у д ,ьш
ь ш ее
о С Ш о |э о Ж Н ь 1 !
UCP сначала компилирует, При каж дой ком пиляции програм ­
мы в папку bin пом ещ ается свежая
потом запускает на Выполнение копия базы данны х. Все д анны е, н а­
При запуске программы ИСР выполняет две операции. Сна­ копленны е с м ом ента последней от­
чала она строит программу, затем вы п олн яет ее. Эта работа л адки, при этом уничтож аю тся.
состоит из нескольких этапов. Код компилируется, то есть В процессе отладки, если код был
превращается в исполняемый файл. Этот файл вместе с дру­ изменен, ИСР перестраивает про­
гими ресурсами помещается в подпапку папки bin. грамму — это означает, что база
данных может оказаться перепи­
Свой исполняемый файл вместе с базой SQL вы найдете санной. Этой проблемы можно избе­
в папке b in /d e b u g . Его запуск позволяет сохранить все вне­ жать, запуская программу из папки
сенные в процессе пользования приложением изменения. b i n / d e b u g или b i n / r e l e a s e или
В то время как при запуске из ИСР база заменяется копией предварительно воспользовавшись
с данными из окна database Explorer. установщиком.

68 глава 1
эффективность с C#

Визуальные Обмкты Х{;айиАище инструменты


Как превратить ВАШ Е прило)кение обьвкты
■NET
базы данных
•НЕТ
Ззяных внедрения

В прило)кение для ВСЕХ


И и "
Пока что приложение работает только на вашем компью­ j
тере. Никто не может им воспользоваться, купить его у вас,
W
увидеть, какой вы замечательный программист и нанять
на работу... даже начальник и клиенты не видят сообщения
из вашей базы данных.
.1 здесь
C# позволяет легко внедрить созданное вами приложе­
ние. Внедрением называется установка программы на дру­
гие компьютеры. В ИСР Visual C# эта процедура осущест­
вляется в два этапа.
При посмюоении
'СктШН- решения файлы
» Wew Project „ 0^ копируются на
'2 3 'H / M A dd W indows Form... ваш компьютер.
^ jj ''J Add Class... Процедура п у ­
бликации созда­
M d M e» item ...
ет выполняемый
1' ^ A dd Existing Item.,.
конфигурационный
Выберите команду Publish файл, при п о ­
MA Ref«teiKe...
Contacts в меню Project. M i Seiw ce Reference.,, мощи которого
SelasaaitUpPmject программу можно
установить на
@ C o n to rts Properties.«
любой компьютер.
Publish C ontacts k

О Щелкните на кнопке Finish


в окне Publish Wizard. Ваше
Publish Wo:a*ti

Where d o you w ant to publish tfw application?


приложение будет обра­ #
ботано, и вы увидите пап­
^ c % t h e location to pubfehthK si^iltcattore
ку в которую сохраняется
ШШ
файл setup.exe. Шp i^ .
You may pubfish the appftcetton to a web site, FTP s«ver, or
bamptes:

Fife share WarveAmyappBcatton

Web 5йе htt(K//www. mkroEt^conv'myappfic*rtion

В Visual Studio Express


Команда Publish
находится в меню Project,
в то время как в других
версиях Visual Studio
ее можно обнаружить
в меню Build.

1 ^ Previ&us j| ... ] ( Imish J j. ^ ^ 1

дальше > 69
поделитесь любовью

Передаем прило}кение пользователям


После внедрения у вас появится папка с именем p u b l i s h / .
В ней находятся все компоненты, необходимые для установки.
Самым важным из них является файл s e tu p . Именно он позво­
ляет установить приложение на любой компьютер.

цНСтДЛАЯЦи^.

руды пе
оС Щ о|Э оЖ Н Ь 1
Д л я ин стал л яц ии вам
м огут пона д об итьс я права
а д м и н и стратора. э т о т файл говорит С помощью этого
файла осуществляется
Если у вас еще нет базы инсталляция.
SQL Server Compact, ин­ в инстйлдмру^ллу
сталлятор автоматически прогряллму-
скачает и установит ее.
На некоторых компьюте­
рах это возможно только
при наличии у вас прав
администратора. Щелкни­
те правой кнопкой мыши Секретарь сказала, что у нас уже
на файле setup и выберите работает новая база данных с контактами.
команду Run as administrator. Вы хорошо поработали и заслужили
Если у вас нет такой воз­ небольшой отдых...
можности, ничего страш­
ного. Это не помешает
вам выполнять следующие
задания.
А
1Саже,тся, начальник доволен.
V Но перед т е м кяк собирать
^ i o / a H b b -Р о т е с т и р у ш
резулЕ?тдтЬ 1 своего тру

70 глава 1
эффективность с C#

Визуадьные Объекты XfsBu/iim« ІІнетрумвиі


Работа НЕ окончена: проверим объекты
•NET
базы ааявы*
. .NET
данных внедрения

процесс установки It
Перед тем как открыть бутылку шампанского и отпразд­
новать победу, нужно протестировать внедрение и уста­ В ; Щ
новку
Закройте ИСР Visual Studio. Запустите файл setup и ука­
жите, куда следует установить ваше приложение. Убе­
дитесь, что все работает так, как вы ожидали, — можно Б:ы здесь
добавлять и редактировать записи, и все изменения со­
храняются в базе данных.

Objectville Paper Com pany Contact List


Стрелки
и текстовое la ill of§ I ^ И !Ф К a
поле позволяют
переходить Coftad ID; I '

от одной записи
к другой, ч ^ Name:

Company: Black Bax Inc.

Tdephone: (718)555-5638

Bnail: Uones@d3lackbo3dnc .com

Oert: a <-
Попробуйте,
вн&сти изменения LaS Ы1: edi sda , fv:3>‘ 26. 201С Q »"
б данные. Все контакты
на месте. Ведь
они являются
частью
базы данных
ContactDB.sdf,
которая была
установлена
вместе
ТЕСТИРУЙТЕ ВСЁ! с приложением.

Тестируйте вашу программу,


процедуру внедрения, данные
в вашем приложении.

дальше ► 71
быстрее не бывает

Управляющее данными Визуальные


объекты
О бм кш ы
базы данных
Х|1ана«още
данных
инструменты
Внедрения
■NET .NET

приложение готово
Visual Studio позволяет с легкостью разработать
Windows-приложение, написать базу данных и свя­
зать эти два объекта вместе. Вы даже смогли по­
строить программу-инсталлятор всего нескольки­
ми дополнительным щелчками мыши.

Q m б у м а ж н о й к а ]= ^ о Ч к и
«Ц: Objectville Paper Company Contact list
Hi 4 \1 crf6 : ► И ! Я
Имя: LloydJones О — Cortad ID: 1 ............ }
Фирма: Black Box Inc. Name; Ltoyd Jones
Телефон: (718)555-5638 До эЛ еК- Csmpanjr: Hack Box Inc.
ЗРроННой Tdeptone; (718)555^638
Email: Uones@Xblackboxinc.com
finaS: U o n e s # > d 3 l a c k b o * i n c .c o n i
Клиент; Yes Поел, звонок: 05/26/07
a « : В
LaSCd: Wednesday, May Ж 2010

наМноГо бьхсгорее,
Чем к а з а л о с ь .

Средства Visual C # позволяют сфокусироваться на


выполнении задания, ведь вам уже не требуется
писать код для окон, кнопок и доступа к базе SQ,L.

72 глава 1
2 ЭЗЦО Б с е Г о Л и Ш ь К о д

Под покровом

Вы — программист, а не просто пользователь ИСР.


И С Р может сделать за вас многое, но не всё. При написании приложений
часто приходится решать п о в т о р я ю щ и е с я задачи. Пусть эту работу вы­
полняет ИСР. Вы же будете в это время думать над более глобальными ве­
щами. Научившись п и са т ь код, вы получите возможность решить любую
задачу.
к вашим услугам

Когда ßbi делаете это...


Все эт и задачи являются
ИСР — это мощный инструмент. Но это всего лишь инструмент. При стандартными
каждом вашем действии он автоматически создает код. Но это хорошо и требую т шаблонного
только при выполнении ш аблонны х задач или в случае, когда код мо­ кода. Поэтому их можно
жет быть использован без дополнительных изменений. отдать на от куп ИСР.

Посмотрим на действия ИСР при разработке типичного приложения.

Создание формы в W indows


ИСР позволяет строить различные приложе­
!:т
ния, но сейчас мы рассмотрим вариант Windows
Forms — программу, имеющую визуальные эле­ '9 =
менты, например, формы и кнопки.

При выборе варианта


W indow s Form s A p p lic a tio n
ИСР создает пуст ую ф ор­
м у и добавляет ее к новому
проекту.

О П ер етаски в ани е кнопки с п анел и инстру­


ментов на qx>pMy и двойной щ елчок на н е й .
Именно кнопки заставляют форму работать.
На их примере мы будем рассматривать различ­
ные аспекты языка С#. Кроме того, они явля­
ются частью практически любого создаваемого
приложения.

Properties X
о Задание свойств qjopMU Form! Sy5tem.Window$.Ferms.Form

Окно P ro p e rtie s позволяет легко поменять .


SbowlnTasfcbar "frt«“
атрибуты практически любого компонента I' Size 4 0 a 261
программы. StzeGnpStyte
StartPosJtron
Auto
WirvdowsOefaultlocatt.
Tag
1O t^ e c t^ ^ Cons
TopMost False

Окно Properties ^
TransparencvKey
UieWaitCursor
□Fafs« .'3
‘простой способ самый / WindowState Normet

Text
><ода формы F orm i Th« text essocmed wrtb the control.

£сли это окно


>^мите клавишу

74 глава 2
это всего лишь код

...UCP делает это.


Любые ваши действия приводят к изменениям
кода, а значит, и файлов, которые содержат этот
код. Иногда редактируются всего несколько стро­
чек, а иногда система создает новые файлы. Эти файлы были
созданы на базе шаблона

.ИСР создает ф айлы и п а п ки .

— '1 ^ Ь' ijs


cU» Fm S
М - Г»«**-«
; J ^ 1 J
W in d o w sA p p licatio n I F o rm l .cs F o rm l .D esigner.cs Program .cs Properties
.csproj

О ...И С Р добавляет код в qэaйл F o r m l . D e s i g n e r . c s , отвеча­


ю щ и й за появление кнопки на <рорме. А затем добавляет
в ф айл F o r m l.C S - код. определяю и^ий результат щ елчка «1ам P»e{
fkblit...
на кн о п ке. }.
p r iv a te v o id b u tto n l_ C lic k (o b je c t sender, E v e n t A r g s e)
F o rm l .Designer.cs

1АСР м о ж е т добавить пустой


метод для обработки щелчка
на кнопке- Но выбор параметров
этого метода — ваша работа.
Form l.C S

о ...И С Р открывает ф айл F o r m l . D e s i g n e r . c s


и обновляет строчку кода.
ИСР открывает ф а й л-

p a r t i a l c l a s s Forml

t h i s . T e x t = " O b j e c t v i l l e P a p e r Company C o n t a c t L i s t " ;

F o rm l .Designer.cs

„u обновляет эт у cvnpomy.

дальше > 75
средства коммуникации

Как ро)кдаются программы


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

Любая программа начинается с файлов, те кста кода


Как вы уже видели, ИСР сохраняет вашу программу в файлы. Эти фай­
лы можно открыть и найти все добавленные к проекту элементы: фор­
мы, ресурсы, код и прочее.
ИСР можно представить как хороший редактор файлов. Он автома­
тически делает отступы, выделяет ключевые слова цветом, закрывает
скобки и даже предполагает, что вы напишете в следующую секунду.
Другими словами, именно ИСР редактирует файлы, содержащие вашу
программу.
ИСР связывает все файлы программы в реш ение путем создания фай­
ла (. s in ) и папки, в которой оказываются все материалы. Решение Программы
содержит список всех входящих в проект файлов (оно имеет расшире­ можно писать
ние . c s p r o j ) , последние же в свою очередь включают в себя список даже в Блокноте
(Notepad), но это
всех файлов, связанных с программой. В этой книге мы будем строить очень долго.
решения на основе всего одного проекта, но окно Solution Explorer по­
зволяет работать и с другими проектами.

инструм енты om.NET Framework


C# — это всего лишь язык, и сам по себе он не может ничего делать.
Но здесь вам на помощь приходит технология .NET Fram ework. При
щелчке на кнопке развертки окна на весь экран срабатывает код, ука­
зывающий, как именно должна выполняться эта операция. Этот код
является частью .NET Framework, как и другие кнопки, флажки, спи­
ски и даже механизмы связи с базой данных. Это хороший инструмент
для создания графики, чтения и записи файлов, управления наборами
объектов и прочих рутинных операций.
Инструменты .NET Framework находятся в пространствах имен. Вы уже
видели их ранее, в верхней части кода. Это было пространство System .
W indows. Forms —именно здесь содержатся кнопки, флажки и формы.
При создании любого проекта Windows Forms в верхней части кода вы
увидите строчку u s in g System . Windows. Forms.

76 глава 2
это всего лишь код

Создание исполняемого файла


Выбор команды Build Solution (меню Build) начинает компи­
ляцию вашей программы. Запускается компилятор, то есть
инструмент, читающий код программы и преобразующий его
в исполняемый файл. Этот файл сохраняется на диск компью­
тера с расширением . е х е . Для запуска программы достаточно
дважды щелкнуть на его имени. По умолчанию этот файл поме­
щается в папку bin, вложенную в папку project. При публикации
решения он (вместе с другими нужными файлами) копируется
в выбранную вами папку.
В ответ на команду Start Debugging (меню Debug) ИСР компи­
лирует программу и запускает полученный файл на выполне­
ние. Существуют и более совершенные инструменты отладки,
то есть запуска программы с возможностью прерывания, чтобы
вы могли понять механизм происходящего.

Программы работают В CLR


Двойной щелчок на имени исполняемого файла запускает
программы. Но между операционной системой и программой
существует дополнительный «слой», называемый Common
Language Runtime, или CLR (общеязыковая исполняющая
среда). Раньше (еще до изобретения С#) писать программы
было намного сложнее, так как приходилось иметь дело с аппа­
ратным обеспечением, заниматься низкоуровневым програм
мированием. CLR —часто называемая также виртуальной ма­
шиной —является своего рода «переводчиком» между вашей
программой и компьютером, на котором она работает. На данном э т а п е
достаточно запомнить,
Функции CLR будут рассмотрены позднее. Пока упомянем
что с и я автоматически
только, что она отвечает за работу с памятью компьютера, запускает ваши
определяя, что программа закончила работать с конкретными программы- Более
данными, и избавляясь от них. Некоторые программисты при­ подробно она будет
выкли самостоятельно работать с памятью, но без этого мож­ рассмотрена позднее.
но обойтись, переложив заботу на CLR.

дальше * 77
ваш маленький помощник

Писать код помогает UCP


с частью возможностей ИСР вы уже познакомились.
Здесь же мы более детально рассмотрим некоторые
инструменты.

о О кно Solution E xp lo rer содержит сп и со к всех частей проекта


Вам предстоит переключаться с одного класса на другой и проще всего
это делать, используя окно Solution Explorer. Вот вид этого окна после
создания программы обмена контактными данными:

Solution Explorer » П X

Ä ij S t . ; .
)
*33 Solution 'Contacts' (1 projectj
^ I^ ^ C o n ta ctsi В окне Solution Explorer
Можно посмот реть,
^ ^ Properties о каких папках на -
l> References ходятся те или иные
appxonfig файлы.
ContactDB,sdf
Ej . ContactDBDataSet.xsd
i> Э Forml .cs
Progrann.cs

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

открыты две
вторая с кодом,
пользуйтесь

78 глава 2
это всего лишь код

ИСР п о м о гае т писать код


Замечали ли вы в процессе набора кода маленькое всплывающее окошко? Это
крайне полезная функция 1п1е1И8еп8е. Она показывает возможные способы завер­
шения строчки кода. Например, если вы набрали слово М еззадеВох и поставили
точку, дальше может следовать только:
ИСР знает, что MessageBox имеет три
MessageBox. метода: Equals,, ReferenceEquals и Show.
Ф Eq ua ls Паи вводе буквы S будет выбран вариант
Show. Вам останется нажать Enter.
# ReferenceEquals Иногда эта функция очень экономит
,ф | время.

Если после выбора варианта Show напечатать (, функция IntelliSense предложит


вам варианты заполнения строки:

Суще-ствует H essageB ox.Show d ______ __________________________________ _________________________ ____________


ЯЗ- способ «essageBox.ShOM(string text, string caption)
вызова метода
Displays 3 message box with specified text and caption.
Show для
MessageBox. tart; The text to display in the message box

В ИСР существуют сокращения, называемые ф рагм ентами кода. Для их вставки


достаточно напечатать нужную аббревиатуру. К примеру, если напечатать ttibox
и дважды нажать клавишу Tab, появится строка для метода M essageB ox. Show:

MessageBox. Show! J
В окне Error
List бк>! найдете
список всех
О кно E rro r L ist показы вает ош ибки ко м п и л яц и и ошибок,
мешаьош,1^Х
Вы даже не представляете, как легко сделать опечатку при наборе кода на С#! компиляции
К счастью, существует инструмент, позволяющий бороться с этой проблемой. iA.pozpaMMt><-
При построении решения всё, мешающее компиляции, будет перечислено
в окне Error List, расположенном в нижней части экрана:

О 2 Errors 1 О W a rn in g s M i ) О M e s sa g e ^
О т сут ст вие tin e C o lu m n P roject
D escription Fite
точки с запятой
после оператора
является одной
из самых частых
ошибок.

Для исправления некорректного кода дважды щелкните на ошибке:


p r i v a t e v o id p ic tu r e B o x l_ C lic k (o b je c t s e n d e r , EventArgs e )
{ Некорректный код
Mess age Box. X>g( h i ) подчеркивается
} красным цветом.

дальше ► 79
подробности

Любые действия Ведут к изменению кода Значок «Упражнение!»


является сигналом
Посмотрим, каким образом ИСР пишет код. Откройте к запуску Visual Studio, л
Visual Studio и создайте новый проект Windows Forms
Application.
^ ^ і/
Уп]^ажнение!

П р осм о тр кода і
Откройте файл F o r m l.D e s ig n e r .c s , но не в конструкторе форм. Для этого Ж
щелкните правой кнопкой мыши на имени файла в окне Solution Explorer и вы­
берите команду View Code. Посмотрите на объявление класса Forml:
p a r t i a l c l a s s Form l

м. .olTopZZZ.
О Д обавление к срорме эл ем ента PictureB ox
Привыкайте работать с множеством вкладок. Вернитесь в окно Solution Explorer
и откройте конструктор форм двойным щелчком на имени файла F o rm l. cs. П е­
ретащите на форму элемент PictureBox.

О П р осм о тр созданного конструктором для элем ента P ictureB ox кода


Вернитесь на вкладку Form LDesigner.es. Найдите вот эту строчку:
Щ елкните на квадратике
Ґ со знаком «плю с».
+ Windows Form D e s ig n e r g e n e r a te d code

Щ елчок на этом квадратике раскроет код. Найдите в нем следующие строчки:

//
// p ictu reB o x l
//
Ваши значения
th is .p ic tu r e B o x l.L o c a tio n = new S y s t e m . D r a w i n g . P o i n t ( 2 7 6 , 2 8); параметров
Location
th is.p ic tu r e B o x l.N a m e = " p ic tu r eB o x l" ; и Size будут
отличать>ся
t h is .p ic t u r e B o x l. S iz e = new S y s t e m .D r a w in g . S i z e (1 0 0 , 50); от указанных
th is.p ic tu r e B o x l.T a b ln d e x = 0;
в книге.

th is .p ic tu r e B o x l.T a b S to p = fa lse ;

80 глава 2
это всего лишь код

Ч то >ке Все это значит? Чаще всего комментарии


помечаются двумя косыми
в верхней части кода вы увидите строки: слешами (//)■ Но ИСР
иногда м о ж е т поставить
три слеша.
/// <sum m ary>
/// О бязательны й м е т о д для поддерж ки к о н с т р у к т о р а - не и зм ен я й т е
/// с о д е р ж и м о е д а н н о г о м е т о д а п р и пом ощ и р е д а к т о р а к о д а .
/// < / sum m ary> Это комментарии XML,
о которых вы узнаете
в разделе # 1 Приложения.

Для детей нет ничего более притягательного, чем табличка с надпи­


сью «Не трогать!» Не отрицайте, вы же знаете, что вам тоже хочет­
ся... поэтому отредактируем содержимое данного метода, воспользо­
вавшись редактором кода! Добавьте к форме кнопку и выполните
следующие действия:

О О тредактируйте свойство T e x t кнопки b u tto n l. К а к вы


д ум аете, что изм енится в окне P roperties?
Сделайте и посмотрите, что получится! Затем вернитесь в кон­
структор форм и проверьте свойство Text. Оно изменилось?

О Воспользуйтесь окном P rop erties для редактирования


Для просмотра
свойства N am e како го -н и б уд ь объекта. результ ат а
В окне Properties это свойство находится вверху и называется
“(Name)». Какие изменения произойдут с кодом? Обратите внима­
ние на комментарии. U запускать
программу.
О п р и с в о й те свойству Location значение ( 0 ,0 ) . И зм ените
парам етр S iz e , увеличив размер кно пки . Form l.cs [Реядп].
У вас получилось?

0 Вернитесь в конструктор кода и произвольным образом


пом еняйте свойство BackColor.
Внимательно посмотрите на код Form l .D e s i g n e r . c s. Появи­
лись ли в нем новые строчки?

Поменять код проще всего средствами ИСР.


дальше > 81
программа делает заявление

Структура программы
имен, отделяя ^о/^® ^^Я-янстбо
■n e t F r a m e Z r L
Код любой программы на C# структурируется
одинаково. Все программы используют про­
странства имен, классы и методы.

Класс содержит^
ф рагм ент вашей
программы (очень
маленькие програм ­
мы м огут состоять
из всего одного класса)

Класс включает один или


несколько методов. Методы всегда
^ и н а д л е ж а м какомц-лиЗп классы
методы. 6 сбою очередь, состоят
из операторов.

Внимательно рассмотрим код


Откройте код проекта Contacts F o rm l. c s , что­
бы рассмотреть его фрагменты.

О *айл кода начинается с перечисления инструментов .NET Framework


в верхней части любого файла программы вы обнаружите набор строк, начинающихся
с оператора u s in g . Они указывают, с какой частью .NET Framework будет работать про­
грамма. Чтобы использовать классы из других пространств имен, нужно указать их при
помощи директивы u s in g . Для построения форм применяется множество инструментов
.NET Framework, поэтому в начале программы так много строк с директивой u s in g .

using System;
using System.Collections.Generic;
Такие строчки
using System.ComponentModel; находятся в верхней
части любого кода.
using System.Data; 1^ажаая из них
показывает, какое
using System.Drawing;
using System.Linq; из .NET Framework
использует т от
using System.Text; или инои файл .CS.

using System.Windows.Forms;
В принципе без оператора u s in g можно обойтись, если пользоваться полными именами.
Если строчка u s in g System .W indow s. Forms отсутствует, окно сообщений можно создать,
написав S y s te m . W indows. F o rm s. M essageB ox. Show(), и компилятор все равно поймет,
какое пространство имен вы имеете в виду.

82 глава 2
это всего лишь код

0 ТТрогроААМЫ н а C # и с п о л ь з у ю т кл а с с ы
Программы на C# используют классы. Каждый класс выполняет свою задачу. Когда вы соз­
давали свою первую программу, ИСР добавила класс Form l, отображающий формы.

Для программы Contacts, ИСР создает


tr одноименное пространство имен. Именно в этом
namespace Contacts пространстве находится все содержимое скобок.

ргоЬИс partial class Forml Form


^ Класс F o rm l содержит код создания как самой
{ формы, так и ее элементов управления. ИСР
добавляет эт от класс при создании проекта
Windows Form Application.
Классы содержат методы
Для выполнения различных действий классы используют метод. Метод берет входные
данные и производит некоторое действие. Данные передаются при помощи параметров.
Именно от них зависит поведение метода. Слово v o id перед названием метода означает,
Обращайте
внимание что он не возвращает никаких параметров.
на пары
скобок. Среди Здесь вызывается мет од
них м огут piiblic Forml О tnitializeComponent().
попадаться
вложенные. {
InitializeComponentO;
}
Каждый оператор выполняет только одно действие
Строкой M essageB ox. Show {) вы добавляете оператор. Именно из операторов составле­
ны методы. При вызове метода выполняется сначала первый оператор, потом следующий
и т. д. Достигнув конца списка операторов или оператора r e t u r n , метод завершает работу.

МетоЭ pictureBoxi-^ChckO Этот метод имеет


вызывается два параметра:
графическом фрагменте. sender и е.

private void pictureBoxlClick(object sender, EventArgs e)


{
MessageBox.Show("Contact List 1.0", "About");
Оператор вызывает метод Show(),
} принадлежащий классу MessageBox в
Это операт ор, вызывающий пространстве имен System.Wlndows.Forms.
диалоговое окно.

Оператор передает методу Show Q два пара­


метра: строку, которая будет отображаться
в окне диалога и заголовок этого окна.

дальше > 83
еще более подробно

Начало работы программы Нй С*


оозможна илолько
При создании нового решения ИСР добавляет файл Program .cs. Най­ одна точка входа
‘^ о мет од MainQ
дите его в окне Solution Explorer и дважды щгелкните на имени. Внутри
класса P rogram вы обнаружите метод M ain {). Этот метод является точ ­
кой входа, то есть именно отсюда программа начинает работу.

Этот код, автоматически созданный


6 упражнении из предыдущей главы.
бы найдете в файле Program.cs.
|( о д Лод уВеЛиЧгадеЛьНьхМ сзиеКЛоМ
а
using System;
using System.Linq;
using System.Collections.Generic;
using System.Windows.Forms;
О \Cod находится
6 пространстве
namespace Contacts
имен Contacts.
{ о
static class Program и более косые черты
{ I/
/ в начале строки обозначают
комментарии.
/// <s\jmmary>
/// Точка входа в приложение
I I I </summary>
[STAThread] Программа начинает
работу с точка входа.
static void Main О
{ О
Application.EnableVisualStyles();
QApplication.SetCompatibleTextRenderingDefault(false);
Application. Run (new FormlO);^ Этот оператор создает
и отображает форму
} Contacts, а также
завершает программу
} при закрытии формы.

, част ь им ени
1<ласса и л и м е т о В а н а ­
Сь~лча^, на стадии начального
з ы в а е т с я о б ъ яв л е н и ем . ^ знакомства с кодом, вам требуется
только понять, на что следует
обращать внимание.

84 глава 2
это всего лишь код

Постепенно вами
программы 5удцт
содержать все дольше
пространств имен.
О Встроенные функции C # и .NET.
Подобные строчки находятся в верхней части почти
всех файлов классов С#. S ystem .W indow s.F orm s Без строчки using вам
это пространство имен. Строка u s in g S y stem . придется в явном виде вводить
Windows . Forms дает программе доступ ко всем объ­ Sustem.Windows. Forms при
ектам этого пространства. В данном случае к визу­ обращении к объекту из этого
альным элементам —кнопкам и формам. пространства имен.

Q Выбор пространства имен для кода.


ИСР назвала созданное пространство имен
Пространства имен
C o n ta c ts (в соответствии с именем проекта).
позволяют использовать одни
Именно этому пространству относится весь код. и те же имена в различных
программах, при условии, что
программы не принадлежат
к одному пространству.
О Код принадлежит к конкретному классу.
В вашей программе этот класс называется
Program . Он содержит код запуска программы
и код вызова формы Contacts. В
несколько классоб.

Технически програм м а
Наш код содержит один метод, состоя­ ^ может имет ь несколько
щий из нескольких операторов.
Внутри любого метода может находиться произ­ \ только у к а за т ь , кякои из
вольное количество операторов. В нашей про­ -V них будет точкой входа.
грамме именно операторы вызывают форму
Contacts. Любая программа на C#
должна иметь единственный
Точка входа. метод Main. Он является
Каждая программа на C# долж на иметь один ме­
тод с названием Main. Именно он выполняется точкой входа дая вашего
первым. C# проверяет классы на его наличие,
пока не находит строчку s t a t i c v o id M ain (). кода.
После этого выполняется первый и все следую­
щие за ним операторы.
При запуске кода метод
M ain() выполняется
ПЕРВЫМ.

дальше > 85
элегантные решения

Редактирование точки Входа


в программе главное —наличие точки входа. При
этом не имеет значение, к какому классу принад­
лежит содержащий ее метод и какие действия
Упражнение! Яагуцщцте. ч т о
производит. Откройте программу из главы 1
и удалите метод Main, чтобы создать его заново. и-ромзоияло п р и
изменении имени
метода, и ваши
соображения
о причинах этого
В файле P ro g ra m . c s присвойте методу M ain имя NotM ain и попро­ явления.
буйте построить и запустить программу. Что произойдет?

О Создадим новую точку входа. Добавьте класс с именем A n o th e rC la s s .e s . Для этого


щелкните правой кнопкой мыши на имени файла в окне Solution Explorer и выбери­
те команду A dd»C lass... ИСР добавит в программу класс A n o th e rC la s s . После этого
код примет вид:

u s in g System ; В файл были добавлены


u sin g S y stem .L in q ; четыре стандартные строчки
u sin g S y ste m .C o lle c tio n s.G e n e r ic ; с оператором using.
u sin g S y stem .T ex t;
Этот класс тоже находится
nam espace C o n ta c ts в пространстве имен
{ Contacts.
c la ss A n o th e r C la ss

} имени файла). основе


Q Добавьте в верхнюю часть строку u s i n g S y s t e m . W in d o w s . F o r m s ;
He забудьте, что в конце строки должна стоять точка с запятой!

О Добавьте этот метод к классу А п оЬ Ь егС Х а в з, написав его внутри фигурных скобок:
Класс MessatjeBox
принадлежит c l a s s A n o th e r C la s s
пространству имен {
System.Windows. p u b lic s t a t i c v oid MainO
Forms, поэтому
на шаге # 3 вы {
и добавили оператор M e ssa g e B o x . Show ( "Fow l" ) 7
using. Метод Show О }
является частью
класса MessageBox.

86 глава 2
это всего лишь код

Ч то )ке произошло?
Теперь вместо приложения Contacts программа вызыва­
ет вот такое окно диалога. Переопределив метод M ain (),
вы указали новую точ 1су входа. Поэтому программа пер­
вым делом выполняет оператор M essageB ox.Show O .
Данный метод больше ничего не содержит, поэтому
после щелчка на кнопке ОК программа завершит свою
работу.

Подсказка: Д о с т а т о ч н о
о Верните программу в исходное состояние. измеш т ь^пару строк
в двух файлах.

_ |Jo3bMH в руку карандаш


Опишите назначение различных строк кода, как показано
в примере.

u s in g S y stem ; Оператор. .«SIM


u s in g S y ste m .L in q ;
u s in g S y s te m .T e x t;
........
u sIn g S y s tern. W indow s. F orm s;

n am esp ace SomeNam espace

{
c l a s s M yC lass

p u b l i c s t a t i c v o id D o S o m e th ln g () {

M e ssa g e B o x .S h o w (" З д ес ь б у д е т соо б щ ен и е" );

дальше > 87
время получить ответы

Часто
^аД аБ аеМ ы е
B o lIp o C b i

Какую роль играют фигурные 3 * Объясните, пожалуйста, еще раз, Почему при запуске программы
скобки? что такое точка входа. в окне Error List появляется сообщение
об ошибках? Я думал, что подобное
О ? Скобки группируют операторы С I Программа состоит из множества возможно только при выполнении
в блоки и используются только попарно. операторов, но они не могут выполняться команды Build Solution.
Открывающей скобке всегда должна соот­ одновременно. Операторы принадлежат
ветствовать закрывающая. разным классам. Как же при запуске С I Первое, что происходит при запуске
программы определить, какой оператор программы на выполнение, это сохране­
Для выделения пары скобок достаточно выполнять первым? ние всех файлов в виде решения и по­
щелкнуть на любой из них. пытка их компиляции. А при компиляции
Компилятор просто не будет работать при кода — неважно, запускаете вы при этом
отсутствии метода M a i n (), который и на­ программу или строите ее решение — все
зывается точкой входа. Первый оператор имеющиеся ошибки отображаются в окне
этого метода и будет выполняться самым Error List. f
первым.
В тексте кода ошибки
выделяются красным
цветом.
Возьми в руку карандаш
Вот правильные варианты ответа на вопрос о строках.

О перат ор losing добавляет


u s in g S y stem ; в класс из Э р уги х
u s in g S y ste m .L in q ; прост ранст в иМеи.
u s in g S y s te m .T e x t;
u s in g S y stem .W in d ow s.F orm s;

n a m esp ace SomeNam espace


Мы указываем, к какому
классу принадлежит
{ эт от фрагмент кода. Внутри этого
класса находится
c l a s s M yC lass { метод DoSometking,
вызывающий объект
p u b l i c s t a t i c v o id D o S o m eth in g lT ”^
MessageBox.
M e ssa g e B o x .S h o w (" З д есь б у д е т собщ ение")

Этот оператор
вТет о к н о с т екст овы м
сообщением.

88 глава 2
это всего лишь код

Определите соответствие описаний и фрагментов кода. (Некоторые


из них вам незнакомы, попробуйте угадать их функцию!)

partial class Forml

Задает свойства объекта label.


this.BackColor = Color.DarkViolet;

Это всего лишь комментарий, до­


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

partial class Forml

private void InitializeComponent( Убирает кнопку сворачивания


{ окна (^ S ) окна F o r m l из строки
заголовка.

number_of_pit_stopsLabel.Name
= "nuraber_of_pit_stopsLabel";
number_of_pit_stopsLabel.Size
Подсказки системы, объясняющие
= new System.Drawing.Size(135, 17) назначение различных блоков
number_of_pit_stopsLabel.Text кода.
= "Number of pit st o p s :";

III <summary> Меняет фоновый цвет окна F o rm l.


III При щелчке на кнопке появляется
III графический фрагмент Rover
III </summary>

partial class Forml


Блок кода, выполняемый при от­
крытии программой окна F o r m l .
this.MaximizeBox = false;

дальше ► 89
решение упражнения

КТ9 И H W A E A a I t ?
Вот правильные ответы на вопрос о назначении различных бло­
ков кода. Сравните со своими вариантами!

partial class Forml

this.BackColor = Color.DarkViolet;
Задает свойства объекта label.

Это всего лишь комментарий, до­


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

partial class Forml


{
private void InitializeComponentO
( Убирает кнопку сворачивания
окна ( ) окна Form l из строки за­
головка.

number_of_pit_stopsLabel.Name
= "number_of_pit_stopsLabel";
number_of_pit_stopsLabel.Size
■Подсказки системы, объясняюш:ие
= new System.Drawing.Size (135, 17)
number_of_pit_stopsLabel.Text назначение различных блоков
= "Number of pit st o p s :"; кода.

I I I <summary>
III При щелчке на кнопке появляется Меняет фоновый цвет окна Form l.
III графический фрагмент Rover
III </summary>

partial class Forml


{
Блок кода, выполняемый при от­
this.MaximizeBox = false;
крытии программой окна Form l.

90 глава 2
это всего лишь код

Классы м огут принадле)кать одному


пространству имен S o m eC lasses.cs
Рассмотрим два файла с классами из програм­
мы P e t F i l e r 2 (Домашний любимец) В них со­
держатся три класса: D o g (Собака), C a t (Кошка)
и F i s h (Рыбка). Так как все они принадлежат namespace PetFiler2 {
пространству имен P e t F i l e r 2 , операторы в
методе D o g . B a r k () (Собака лает) могут вызы­
вать операторы C a t . M e o w ( ) (Кошка мяукает) class Dog {
и F i s h . S w i m О (Рыбка плавает). Распределе­
pviblic void BarkO {
ние различных имен пространств и классов по
файлам не влияет на действия, выполняемые/ // Здесь операторы
после запуска. }

class Cat {
public void MeowO {
M oreC lasses.cs

Классы из одного пространства


имен Могут «видет ь» друг друга,
даже находясь 8 разных файлах.
А

Для помещения класса в разные


файлы используйте ключевое слово
partial. Именно его использует
ИСР, создавая файлы Forml.cs
и Forml.Pesigner.cs.

дальше ¥ 91
параметры могут варьироват ься

Ч то такое переменные

Все программы работают с данными. Данные могут быть пред­


ставлены в виде документа, графического фрагмента, видео­
игры или мгновенного сообщения. Для их хранения программа
использует переменны е.
)уды ие I
о а о а о р 'о ж н ы !
Объявление переменных
З наете ли вы д р уги е язы ки
О б ъ яви ть (declare) переменную, значит, указать программе прогр ам м и р о в ани я?
тип и ее имя. Благодаря указанию типов невозможно скомпи­ Если да, то вам, скорее
лировать программы в случае, если вы сделали ошибку и пыта­ всего, уже известна большая
етесь сделать нечто, лишенное смысла, например вычесть Fido часть этого материала. Но
из 48353. выполнить упражнения все
равно имеет смысл, так как
не исключено, что С# чем-то
отличается от известных
Э1ЛЛ0 Эило вам языков.
перем енно.
C ^ in t m a x W e ig h t; ^ \\
s t r in g m e ssage j
bool boxCheckedr

м огут храниться. переменнь 1Х.

Переменные меняются
Для работы
В процессе работы программы любой переменной может быть с числами, тек­
присвоено произвольное значение. То есть значения перемен­
ных меняются. Это ключевая идея любой программы. К приме­ стом, булевы­
ру, если переменной m yH eight было присвоено значение 63:
in t m yH eigh t = 63;
ми значениями
как только имя m y H e i g h t появится в коде, C# заменит его зна­ и любым другим
чением 63. Представим, что позднее ему было присвоено зна­
чение 12: видом данных
m yH eigh t = 12;
используйте
Теперь C# будет заменять параметр m yH eight на число 12, не­
смотря на то что имя переменной не изменилось. переменные.
92 глава 2
это всего лишь код

Присвоение значений
Поместите в программу эти операторы:
int Z ;
Отсутствие у пере­
M e s s a g e B o x . S h o w ("О твет " + z ) ;
менных значения
При попытке запустить программу, ИСР откажет­
ся компилировать код. Компилятор проверил ваши
переменные и обнаружил, что им не присвоено ни­
является препят­
какого значения. Чтобы избежать подобных ошибок,
- <
имеет смысл комбинировать оператор объявления

Присвоенные ствием для компи­
переменной с оператором присвоения значения: значения. ляции. Этой ошиб­
ки легко избежать,
xWeight объединив в один
message оператор объяв­
bxChecked ление переменной
и присвоение ей
ß объявлении переменной, как
и раньше, указывается ее тип.
значения.

Некоторые типы переменных


Тип переменной определяет, какие именно данные в ней можно хра­ верш енной
нить. Подробно типы будут рассматриваться в главе 4, а пока запом­ ^ом еняте.
ните три наиболее используемых типа. Переменные типа i n t сохра­
няют целые числа, переменные типа s t r i n g —текст, а переменные
типа b o o l —логические значения true/false.

пе-ре-мен-ный, пррш.
умеющий меняться или приспосабливаться.
Переменная скорость дрели позволяет Бобу свер­
лить то быстро, то медленно, в зависимости от
текущих задач.

дальше > 93
операторы наготове

Д л я пр о гр ам м и ста сл о во string
Знакомые математические симболы почти всегда о значает «строка
текста», а со кр ащ ен и е int указы ­
Числа, хранящиеся в переменных можно складывать, вы­ в ает на целое число.
читать, умножать и делить. В этом вам помогут о п е р а т о р ы
(o p e r a to r s). Часть из них вам уже знакома. Рассмотрим код,
решающий несложную математическую задачку:
Третий оператор присваивает
переменной num ber значение
Мі?і об-ьябилы пере 3 6 * 1 S = S40. Следующий
М бнкую num ber int number = оператор присваивает новое
целочисленного значение 12. - (42. / 7) = 6.
U присбои nvunber = number
ли ей знйченме
з а т е м .puö^6«A« number = 36
m 6 резул і^тате
О п ератор « :S ^ Im b e r
чего ока іА,олучилй number = 12 - к значению перем
зняченме Я-?-
number += 10; г » « “«
вы получите %■&>■
Оператор *= number *= 3;
означает, что
вы должны ум н о­ number = 71 / 3;
жить текущее л Если71 разделить на 3 получится 2 3 .6 6 6 6 6 6 ...
значение перем ен­ \ __ _ МО результ ат деления целых чисел также должен
ной на 3^ в итоге быть целым, поэт ому 23.666... округляется до 23.
получаем 48. int count =
count ++; Целочисленные переменные используются в счетчике
в сочетании с операторами +-+ и Инкремент ++-
Класс MessageBox count --; увеличивает значения на
вызывает окно а декремент — ум еньш ает на 1.
с текстом «hello
again kello».
String result = "hello"; Оператор + в данном
случае соединяет вместе
result += " again " + result; две строки. При этом
числа авт омат иче­
MessageBox.Show(result); ски преобразовываются
Пустые кавычки к т ипу string.
обозначают строку. result = "the value is: + count;
О
не содержащун:>
символов. result =
Переменные типа
bool принимают
значения true или
false. Оператор ! bool yesNo = false;
обозначает от рица­
ние и меняет зна- bool anotherBool = true; Н е в о л н у й т е с ь , е с л и в ы н е см о гл и
чение с true на false зап ом н и ть в сё.
и обратно. y e ^ o = !anotherBool;
Эта информация будет часто повто­
ряться в книге.
94 глава 2
это всего лишь код

Наблюдение за переменными 6 процессе отладки


Отладчик позволяет понять, как работает программа. Рассмотрим код
с предыдущей страницы.
О Новы й проект W indows Forms Application
Перетащите на форму кнопку и щелкните на ней два раза. Введите код с пре­
дыдущей страницы.
Forrrd.cs D X
ИСР откроет
’^Chepter_2_Code.Formi »I ‘j g ^ b y t t o n X s e n d e r , ЕуепЫ г^ ej
новый проект
■ p riv a te v o id b u t t o n l_ C lic k (o b je c t sen d er, E v e n tA rg s e )
с пустой формой
{ и точкой входа.
I // H ere’ s a g r e a t w a y t o u s if t h e ID E t o see how t h i s c o d e ¥ io r k sl
I U Вы можете дать
\ // F ir st, c re ate a new p r o j e c t in t h e lO E a d d a b u t t o n . I 4 e x t , d o u b l e - c l i c k o n t h e ему любое имя.
! // b u tto n 50 th e lO E a d d s a b u t t o n l _ C l i c k s ^ t h o d t o y o u r p r o g r a m *. F i l l in t h a t
I // ise th o d w ith a i l o f th e cod e, sta rtin g w ith " i n t num ber = 1 5 ; " .
i //
: // p u t a b r e a k p o in t on th e f i r s t lin e by r i g h t - c ii c k in g on i t an d c h o o s in g
; // "B re a k p o in t » I n s e r t B r e a k p o in t" . The l in e sh o u ld tu rn red ,
//
// № e x tj s t a r t d e b u g g in g y o u r p ro g ra *a . Y o u 'l l se e it b r e a k on th e l i n e w h ere you
// in s e r te d th e b r e a k p o in t. Y our p ro g ram ’ s j u s t p a u se d t I f you c li c k t h e Run
/ / t o o lb a r b u tto n (o r h it F 5 )j it 4 # iil c o n t in u e . R ig h t- c lic k on "n u re b e r" an d
// ch o o se ''E x p r e s s i o n : ’ n u fsb e r ' » A dd i ^ a t c h " frcffli t h e ise n u - T h e b o t t o r e p a n e l i n
// t h e lO E s h o u l d ch an ge t o t h e W a t c h e s w in d o w ^ a n d t h e r e s h o u l d be a lin e in th at
/ / w in d o t« f o r " fiu f iib e r ” . S t e p th ro u g h t h e p ro g ra is l i n e by lin e u s in g S te p O ver (F I® )
// You c a n se e th e v a lu e o f th e ’’ n u m b e r’' v a r i a b l e ch an ge e s you g o !
//
// Do t h e sam e f o r t h e c o u n t , r e su lt, y e sfto , an d a n o t h e r B o o l v a r i a b l e s .
Комментарии
выделяются
n u is b e r » n ufflber -f 1@ ; < :r зеленым
num ber = 3 6 * IS ; цветом
n um ber = 1 2 - (4 2 / 7>; и м огут
n u m b e r + = l@ j
содержать
num ber * = 3i
любой т екст ,
num ber = 7 1 / 3 ;
компилятор
in t count »
их не замечает.
c o u n t+ + ;
c o u n t--;
Д ост игнув точки останови
strin g r e s u lt = "h e llo ” ; программа п р е к ^ а щ Т е Т ^
re su lt + * " a g a in ” + re su lt;
H e s s a g e B o K ,S h o w ( r e s u lt ) ; w eS m » “
r e su lt * ” th e v a lu e iis j “ + c o u n t;
re su lt =

b ool yesH o = f a ls e ;
b o o l a n o t h e r B o o l =» t r u e ;
y e sfto = ta n o th e r B o o l;

}
lioo%~

О Вставка точки останова в первую строчку кода


Щ елкните правой кнопкой мыши на строке ( i n t num ber = 1 5 ;) и выберите команду Insert
Breakpoint из меню Breakpoint. (Можно воспользоваться Toggle Breakpoint из меню Debug или
нажать клавишу F9.) .
------------------- ► ЦереВернише страницу и проДоЛжим!
прекратим ошибки!

О О тл ад ка программы
Щ елкните на кнопке Start Debugging (или нажмите клавишу F5) (Можно использовать команду
Start Debugging, меню Debug.) Программа начнет работу и откроет форму.

П е р е х о д к точке останова
Как только программа дойдет до точки останова, ИСР автоматически вызовет редактор кода
и выделит нужную строчку желтым цветом.

О in t пияЬег « I5j
num ber = numiaer + 1 0 j
num ber = 3 6 * I S ; В процессе отладки
; num ber = 12 - (4 2 / 7 ) достаточно навести на
: num ber + = l e j переменную указатель
num ber * = 3 ;
мыши,, чтобы появилось
всплывающее окно
: num ber = 7 1 / 3 j
со значением этой
переменной.

Контрольное значение перем енной number /


Щ елкните правой кнопкой мыши на переменной num ber и выбе­
рите в появившемся меню команду Expression: ‘number’ » Add
Watch. Внизу экрана появится окно Watch:
I
Watch Пx |
1М ате j Velue jType
Ц
і
••• ядЛ ег , :0 ■" ,, /
....... ■■r ..........
Функция Watch
_1
помогает отсле­
_______________[^iWatchJ
живать значе­
О бход кода
Нажмите F10, чтобы обойти эту строку. (Можно также выбрать в ния переменных
меню Debug команду Step Over или щелкнуть на кнопке Step Over
панели инструментов Debug.) Выделенная строка будет выполнена, на каждом эта­
и значение переменной num ber станет равным 15. Теперь желтым
будет выделена следующая строка кода. пе выполнения
Присвоенное
кода. Вы оце­
переменной
значение т ут ните ее удобство
же появилось
в окне Watch. но мере услож­
П родолж ение роботы прогроАлмы
нения ваших
Для возвращения в обычный режим выполнения программы на­
жмите F5 или выберите в меню Debug команду Continue. программ.
96 глава 2
это всего лишь код

Циклы
СОБЕТ^
в большинстве сложных программ одни и те же действия повто­ Наличие непарных скобок, явля­
ряются больше одного раза. В такой ситуации на помощь прихо­ ется препятствием к построению
дят циклы (loops) —они заставляют программу выполнять набор программы. К счастью, достаточно
операторов, до тех пор пока указанное вами условие не примет навести указатель мыши на скобку,
значениёС ^^е (или false])). и ИСР тут же выделит ее «вторую
половину»:
bo o l te st^
w h ile == t r u e )
Вот почему іл'як бйжны
переменные логического {
типа. // C on ten ts o f t h e lo o p

8 цикле while операторы


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

for (int i = 0 ; i < 8 ; 1 = 1 + 2 )


{
MessageBox. Show (''Я появлюсь 4 раза");
}
Написание простого цикла при noMouiu фрагментов кода Количество «прогонов»
цикла зависит от значения
Через минуту вам предстоит написать программу. Эту задачу мож­ ^ р а м е т р а length (длина),
но ускорить средствами ИСР. Если набрав ключевое слово f o r , dm om парамет р может
дважды нажать кнопку Tab, нужный код наберется сам. При вводе быть как константой.
имени переменной оно автоматически появится во всем фраг­ 1^ а к и переменной.
менте. Повторное нажатие кнопки Tab перемещает курсор на
переменную length.

fo r (in t § = if
{
Достаточно изменить имя
переменной здесь, и оно
автоматически изменится
во всем фрагменте кода.

дальше ► 97
приготовились, настроились, кодируем!

еС К о Л ь К о С оБ ехооБ
н
Перейдем к практике
★ Не забывайте, что в конце оператора
Работа программы определяется операторами. Но должна стоять точка с запятой:
операторы существуют не в вакууме. Впрочем, про­ name = " J o e " ;
ще всего это понять на примере. Создайте проект
W indows Form s A pplication. ★ За двумя косыми чертами идут
комментарии:
// этот тек ст игнорируется

★ Объявляя переменную, укажите ее


им я и ти п (типы будут подробно
рассматриваться в главе 4):
i n t w e ig h t;
/ / w e ig h t — ц ел о е число

★ Код для классов и методов заключается


в фигурные скобки:
p u b l i c v o i d Go О {
/ / з д е с ь ваш к о д
}
★ В большинстве случаев количество
пробелов не имеет значения:
in t j = 1234 ;
Оператор, Выводящий сооби^ение это то же самое, что и:
Дважды щелкните на первой кнопке и добавь­ in t j = 1234;
те к методу b u t t o n l _ C l i c k () эти операторы.
Внимательно изучите код и результат его вы­
полнения.

. э то п е р е м е н н а я , in t p r iv a te v o id b u tto n l_ C lic k (o b je c t send er, E v en tA rg s e)

{
м елое им ело, остальная О Л е к т PI относится
часть оператора ^ // э т о ком ментарий
Присваивает п е р е м е н н о й strin g name = " Q u e n t i n " ; Math из пространства
знам ени е 3 . I ^м ен System , поэтами
in t X ^ 3;

X = X * 17; долж нТ''


d o u b le d = M a th .P I / 2; usm gsystem .
M essa g eB o x .S h o w (" n a m e is
n a m e is Q u e n tin + " \n x is " + X
x is 5 1
d is l.5 7 0 7 » 3 2 6 7 9 4 9 + " \n d i s " + d );

^х~о 1^оследовательность,
OK добавляющая в окно сообщения символ
переноса строки.

98 глава 2
это всего лишь иод

О ператоры if/e ls e инициируют действия при выполнении или


невыполнении заданны х условий. В большинстве случаев речь
идет о проверке равенства. Для этого используется оператор ==.
Не путайте его с оператором (=), который присваивает перемен­
ным определенное значение.

о п е р а т о р -Т
с проверки условия.
Л
if (someValue == 24)
{
О „ер а« о р в ф м а Р " » "
MessageBox.S h o w ("Значение 24 ."); . сковах выполняется
со1ли>д‘ ш и
> д л я сравнения аввх » « S e ®
условия.
и сш А И и етея о « ер « ~ о р «
з н » « р «венет6«^

// Количество операторов в скобках


// может быть произвольным
Если заданное
условие соблюдено, MessageBox.Show("Значение 24.");
Выполняется т г
первый оператор, / exse
в противном
случае — второй. — 2^ MessageBox.S h o w ("Значение отлично от 24.");

f i С л ед и те за количеством знаков рав енств а в операторе!


руды не
I Оператор, состоящ ий из одного знака (=) присваивает пере-
о с ш о | - 'о ^ jji, значение, а из двух знаков (==) — сравнивает две пе­
ременные. Эт о очень распрост раненная ошибка. Есл и вы видите сообщение
«невозможно преобразовать тип ‘int’ в тип ЪооГ», скорее всего, именно эта
ошибка является его причиной.

дальше > 99
то, что вы можете сделать

ПроберЬ условий
Рассмотрим работу условного оператора i f / e l s e .
Использование
Проверка при помои^и операторов условного опера
Вы уже познакомились с оператором ==, проверяющим, равны ли
друг другу две переменные. Существуют и другие операторы срав-
тора для сравне
нения:
ния двух чисел
Оператор != в отличие от оператора == принимает значе­
ние true, если переменные н е р а в н ы . называется про­
★ Операторы > и < выявляют, какая переменная больше.

веркой условия.
Операторы ==, ! = , > и < называются о п е р а т о р а м и с р а в н е ­
н и я . С их помощью осуществляется п р о в е р к а у с л о в и й .

Операторы сравнения можно комбинировать при помощи


оператора && (И) и оператора | | (ИЛИ). К примеру, усло­
Для возвращения в режим
вие i равно 3 или j меньше 5 записывается как ( i == 3) II редактирования кода
(j < 5). остановите отладку
программы. Это можно
сделать при помощи
команды Stop Debugging из
меню Debug.
Задание переменной и проверка ее значения
Ниже вы видите код для второй кнопки. Он содержит оператор i f /
else, проверяющий, равна ли целочисленная п е р е м е н н а я х десяти.

p r iv a te v o id b u tto n 2 _ C lick (o b je ct send er, E v e n tA r g s e)


{
^ in t X = 5;
Объявим (if (X == 1 0 )
!^рем енную 'I
XU присвоим M e s s a g e B o x . S h o w (" X m u s t b e 10" );
ей значение s. }
Зат ем п ро- e lse
верим, равна {
ли она 1о. M e s s a g e B o x . S h o w ( "X i s n ' t 10" );
}
}

Это результат работы програм м ы . О тр ед акти р уй те код таким


образом , чтобы со о б щ е н и е и зм ени лось на х m ust be 10.

100 глава 2
это всего лишь код

Проверка еще одного условия


Щ елчок на третьей кнопке должен приводить к появлению В этой строке проверя­
ется, равна ли переменная
окна. Самостоятельно отредактируйте код, чтобы в окне появ­ someValue т рем , и содер­
лялся этот текст. жит ли переменная пате
значение «Joe».
p r iv a te v o id b u tto n 3 _ C lick (o b je ct sen d er, E v en tA rg s e)

{
in t som eV alu e = 4;
str in g name = "Bobbo J r ." ;
if ((so m eV a lu e == 3 ) && (na m e == " Joe" ))

{
M e s sa g e B o x .S h o w (" x i s 3 a n d t h e name i s Joe" );

}
M e s sa g e B o x .S h o w ( " t h i s lin e ru n s no m a tte r w h at" );

Добавление цикла
Ниже показан код для последней кнопки. Он содержит два цикла. Цикл
w h ile , который реализует операторы в скобках, пока выпоняется заданное
условие. И цикл f o r . Посмотрим, как это работает.

p r iv a te v o id b u tto n 4 _ C lick (o b je ct sen d er, E ven tA rgs e)


{
in t count = о;

Цикл работает, Это условие проверяется


пока значение A w h ile ( c o u n t < 10)
переменной { перед началом работы
цикля. Цикл запускается
count меньше 1 0 . count = count + 1;
при соблюдении услобия.

Здесь переменной
используемой Оператор, при
для подсчета каждом проходе
проходов цикла цикла увеличиваю-
присваивается щый значение I на х.
’ . . . - л значение.
н а ч а л ь н о е M e s sa g e B o x .sh o w (" T h e a n s w e r is " + cou n t)
}

П ер ед тем как щ ел кнуть на кнопке, п опы тайтесь по в и д у кода понять,


какое зн ачен и е будет в окне. П роверьте пр ав и л ь но сть св ои х вы водов!

дальше ► 101
выше и выше и выше и...

возьми в руку карандаш


Попрактикуйтесь в проверке условий циклов. Посмотрите на код
и напишите пояснения к каждой его строке.
Заполните
остальные
i n t r e s u l t = 0 ; / / п ер ем ен н ая , в которую б у д е т за п и с а н р е з у л ь т а т строки по
------------ - аналогии.
I n t X = 6; I I объявим переменную х и присвоим значение 6

w h ile (х > 3) {

/ / операторы б у д у т вы полняться, пока

r e s u l t = r e s u l t + х ; / / прибавим х

X = X - 1; / / вычтем

}
for (in t z = l ; z < 3 ; 2 = z + l ) {

/ / начнем цикл с .....................................

/ / 191КЛ р а б о т а е т пока

//на каждом э т а п е , .................................

r e s u lt = r e s u lt + z; / / ....................

}
/ / Следующий о п ер атор вызывает окно д и а л о г а с т ек ст о м

//
M e ssa g e B o x .S h o w (" Р езу л ь т а т р а в ен " + r e s u l t ) ;

Еще о проверке условий


п р о в е р к а условии о су щ е ст в л я е м ся п р и п о м о щ и
о п е р а т о р о в ср а в н е н и я :
X < у (меньше чем)
X > у (больше чем)
X == у (равно)

Э т и о п е р а т о р ы и с п о л ь з у ю т с я ч а щ е всего.

102 глава 2
это всего лишь код

Подождите! А что случится с


циклом, если я напишу условие,
которое никогда не выполняется?

Значит, цикл никогда не закончится!


Результатом каждой проверки условия является
значение t r u e или f a l s e . В первом случае цикл
выполняется еще раз. Рано или поздно вы долж­
ны получить другой результат, и тогда цикл за­
кончится.

цикдізі-

возьми в руку карандаш


Вот несколько циклов. Какие из них являются бесконечными?
Сколько раз выполняются остальные циклы?

Ц и кл # 1 Ц и кл # 3 Ц и кл # 5
in t count = 5; in t 3 = 2 ; in t р = 2;
w h ile (count >0) { fo r (in t і = 1; і < 100; fo r ( in t q = 2; q < 32;
count = count * 3; І = І * 2) q = q * 2)
count = count * -1; { {
‘И = j - І; w h ile (p < q )
} Сколько раз w h ile (j < 25)
будет выполнен {
эт от опера­ { P = P * 2;
тор? j = j + 5;
Ц и кл # 2
in t i = 0; Сколько раз kq = p - q;
}
in t count = 2; будет выполнен ■
э т о т оператор?
w h ile (i == 0 ) {
count = count * 3; Ц и кл # 4
При повторении
count = count * -1 w h ile (tru e) { in t і = 1;} \ 1^тератора ^ = а * 2
помните, что начальное
} значение ^ равно 2..

\
8 цикле for сначала
выполняется проверка
услобия, а потом
итератор.
^ Ш ТУРМ
Подумайте, в какой ситуации может понадобиться
бесконечный цикл? (Один из вариантов ответа вы
найдете в главе 13...)

дальше ► 103
если только, но только если

- 1^озьми в руку карандаш


Решение Вот, как следовало закончить строчки комментариев к програм­
ме, иллюстрирующей работу циклов и проверку условий.

i n t r e s u l t = 0; / / п ер ем ен н ая , в которую б у д е т за п и с а н р е зу л ь т а т

i n t X = 6 ; / / объявим переменную х и ..............

w h i le

/ / операторы б у д у т вы полняться, п ок а X больше 3

r e s u l t = r e s u l t + х ; / / прибавим х К переменной result

X = X - 1; / / вычтем i из пер ем енн о й X

Этот цикл выполняется дважды: сначала при г


} равном 1, зат ем при г равном а . Как только
fo r (in t 2 = Z + 1) {
Z получит значение 3 , условие перест анет со­
блюдаться, и цикл остановится.
11 начнем 191КЛ с обьявления переменной г и присвоения ей значения 1
/ / цикл р а б о т а е т пока Z меньше 3

//на каждом э т а п е значение переменной z увеличивается на 1

r e s u lt = r e s u lt + z; / / п е р е м е н н а я Z п р и б а в л я е т с я к п е р е м е н н о й result

}
/ / Следующий о п ер атор вызывает окно ди а л о га с тек ст о м

M e ssa g e B o x .S h o w (" Р езу л ь т а т равен" + r e s u l t ) ;

Г в руку карандаш
Сравните свои ответы на вопрос, сколько раз будет выполнен
'ешение тот или иной цикл с правильными ответами.

Ц и кл # 1 Ц и кл # 3 Ц и кл # 5
Будет выполнен один раз. Будет выполнен семь раз.
Будет выполнен
восемь раз.
Ц и кл # 2 Ц и кл # 4
Бесконечный цикл Еще один бесконечный цикл.

Попробуйте реш ить задачу номер пять. Это отличная возможность поработать с о т ­
ладчиком! Сделайте оператор с) = р ~ точкой останова и проверьте, как изменяются
значения переменных р и q с помошрю окна Watches■

104 глава 2
это всего лишь код
часвдо
Задаваем ы е
БоЦ|эос;ь1

Всегда ли оператор принадлежит к какому-нибудь клас­ Насколько внимательно нужно относится к автоматиче­
су? ски создаваемому коду?

Г ! Да. Все операторы принадлежат к определенным кпассам,


точно также как все классы, в свою очередь, принадлежат про­
! Относитесь к нему достаточно внимательно. Нужно понимать
соответствие между кодом и вашими действиями, чтобы при не­
странствам имен. Когда вы используете конструктор для задания обходимости иметь возможность отредактировать его вручную.
свойств объектов формы, может показаться, что некоторые опе­ Впрочем, в подавляющем большинстве случаев все необходимые
раторы находятся вне классов. Но внимательное рассмотрение изменения можно проделать с помощью ИСР.
кода показывает, что на самом деле это не так.

Существуют ли пространства имен, которые я не могу КЛЮЧЕВЫЕ


использовать? А как насчет тех, которые я обязан исполь­
зовать?
МОМЕНТЫ
■ Вашу программу заставляют работать операто­
Q l Да, некоторые пространства имен использовать не реко­ ры, которые всегда принадлежат к какому-либо
мендуется, например, пространство имен S y s t e m . Именно там
классу. Класс же, в свою очередь, находится
находятся S y s t e m . D a t a , позволяющий работать с таблица­
в каком-то пространстве имен.
ми и базами данных, и S y s t e m , ю , обеспечивающий работу
с файлами и потоками данных. Но по большей части вы можете ■ В конце операторов стоит знак (;).
называть пространства имен, как вам нравится. Или отдать это на
откуп ИСР, которая будет автоматически создавать имена, взяв за ■ В ответ на ваши действия Visual Studio автома­
основу имя программы. тически добавляет в программу код.

■ Блоки кода, такие как классы, цикл w h i l e , опе­


! А все-таки, зачем нужно ключевое слово partial? раторы if/else и многие другие виды операторов
Б
заключаются в фигурные скобки { }.
( 1 ; Оно позволяет распределять код одного класса между разны­
ми файлами. При создании формы, ИСР сохраняет редактируемый ■ Результатом проверки условия является значе­
вами код в файл (к примеру, F o r m l . c s ) , а автоматически моди­ ние t r u e или f a l s e . С его помощью опреде­
фицируемый — в файл ( F o r m l . D e s i g n e r . c s ) . Но оба они на­ ляется, будет ли закончен цикл, а также какой
ходятся в одном пространстве имен. Достаточно объявить простран­ именно блок кода будет реализован в операторе
ство имен в верхней части файла, и ему будет принадлежать все, что if/else.
попадает в фигурные скобки, расположенные ниже. При этом в од­
ном файле могут находится объекгы из разных пространств имен ■ Для хранения данных используются перемен­
и разных классов. Но об этом мы поговорим в следующей главе. ные. Оператор = присваивает переменной зна­
чение, а оператор == сравнивает значения двух
Что происходит с кодом, который был автоматически переменных.
создан ИСР, если воспользоваться командой Undo? ■ Цикл w h i l e выполняет все операторы в фигур­
ных скобках, пока результатом проверки усло­
^ ; Попробуйте, и вы сами найдете ответ на этот вопрос! Пере­ вия является значение t r u e .
тащите на форму кнопку и поменяйте ее свойства. А затем вос­
пользуйтесь командой отмены. Вы увидите, что в простых случаях ■ Как только проверка условия дает значение
ИСР просто возвращает вас в предьщущую точку. Но при попытке f a l s e , цикл w h i l e прекращает работу, и про­
отменить вставку в базу данных SQ L появится окно с предупреж­ грамма переходит к оператору, расположенному
дением, что после отмены операции вы не сможете отменить свое сразу после цикла.
решение командой Redo.

дальше > 105


ваш код... теперь в виде магнитов

^ а Г н и ш ы С К одам и
Мы поместили блоки с фрагментами кода на С# на магниты для холодильника. Со­
ставьте из них работающую программу, результатом которой является окно с сообще­
нием. Некоторые магнитики упали на пол, и они слишком малы, чтобы их поднимать,
поэтому просто впишите недостающий код от руки! (Подсказка: вам понадобится все­
го пара фрагментов!)

Пустыми кавычками обозначена


пустая строка. Это означает,
что переменная Result еще не со­
держит текста. j

Этот магнит if (X == 2) {
s t r in g R esu lt = упал на пол..
R esu lt = R esu lt + " b e

}
--------------
if (X > 2) {
R e s u l t = R e s u l t + "a";

>
i n t X = 3; 1

Результат:

M essageB ox.Sho w (R e eult);

О ш Б е ш ы н а с. I 3 -

106 глава 2
это всего лишь код
Вам придется выполнить много В процессе чтения книги вам предстоит соз­
подобных упражнений. О т ве­ дать много разных приложений, и все их нужно
ты можно найти на следуюш,ей оудет кйк~т .0 млдснобйте?, Мь>/ совстуем присво-
странице. Если вы не знаете, как umt? эт ому приложению имя «Z Fun with if-else
реш ит ь задачу, не стесняйтесь statem ents» ( z Забава с операторами if-else ), п о ­
подсмотреть. лученное в результ ат е комбинации номера главы
и текста 8 строке заголовка формы.

Попрактикуемся в использовании оператора if/else. Сможете создать программу?


аж нш е
Ф орм а, которую нуж но получить. Д обавь те ф лаж ок.
Перетащите флажок с панели инструмен­
тов на форму и отредактируйте свойство
T e x t . Аналогичным способом нужно будет
отредактировать текст кнопки и метки.
a-J Fun with if/else statements!

Change the color if the


® Бпййе color d ianghg Э то метка.
bexisdiecked
В окне Properties поменяйте размер
Press the шрифта и сделайте его полужирным.
С помощью свойства B a c k C o lo r сде­
лайте фон красным. Выберите вари­
ант R ed на вкладке web colors.

Если поль зов атель забы л постав и ть ф л аж ок, д о л ж н о


вы водится окно, и нф о р м и р ую щ ее его об этом.
Имя флажка c h e c k B o x l . Если флажок установлен, должно соблю­
даться условие:
c h e c k B o x l. C heck ed == t r u e

При установ л енно м ф л аж ке щ ел чо к на кнопке д ол ж ен м енять ф оновы й


цвет метки.
Красный фоновый цвет метки должен меняться на синий. И наоборот. Вот опера­
тор, задающий фоновый цвет метки с именем l a b e l l :
l a b e l l .B a c k C o l o r = C o lo r .R e d ;

(Подсказка: Проверка условия, является ли фоновый цвет метки красным, выгля­


дит практически так же, но с одним маленьким отличием!)

дальше * 107
симпатично!

Построим что-то яркое! Начните с создания нового проекта Windows Forms Application.
п'ражнение
Вот ф орм а, которую
нуж но получить

П ерем енная, э при наличии


cm6yew только внy^v^P^* переменнук>, нужно
ЭвйХ циклов h r '» » « ■ “ " “ “ Г е « “ Й рем е^ная с а * е оЙ.»в-

о С делайте цюновый цвет броским!


Пусть результатом щелчка на кнопке станет ци­
кличное изменение фонового цвета! Создайте
цикл, в котором значение переменной с меняется
от Одо 253. Вот как выглядит код:
th is.B a c k C o lo r = C o lo r .F r o tn A r g b (c , 255 - с, с) ;
A p p lic a tio n .D o E v e n tsО ; ^ ^

перес^анет о Л о в л К м т а к кок уЭмби меня ц б е то м !

\ „ в» MOW-“ зага««»» “
Метод РоЕуепЬв () принудительно на о д g варианты п т
обновляет форму на каждом витке свои собственные р
цикла, но это «обходной» пут ь,
который не следует использовать
в серьезных программах.

о З ам ед л и те процесс
Чтобы цвета менялись медленнее, после стро­
ки A p p l i c a t i o n . D oE vents () напишите:

S y stem . T h rea d in g . T h read . S le e p


ммен system .Threading.

108 глава 2
это всего лишь код

Сглаж ивание процесса


Пусть цветовая гамма возвращается к изначальному цвету. Для этого до­
бавьте еще один цикл, в котором переменная с будет меняться уже от 254
до 0. В фигурные скобки поставьте блок кода из предыдущего цикла.

Сделайте процесс непрерывным находящийся


Поместите два цикла внутрь третьего, который будет выполняться бес- внутри другого
конечно. В итоге щелчок на кнопке будет приводить к непрерывному цикла, называется
изменению фонового цвета. (Подсказка: цикл w h i l e является бесконеч- "-^в^оженным».
ным, если проверка условия дает результат ( t r u e ) ! )

Ой-е-ей! Программа не останавливается!


После запуска этой программы остановить ее работу просто за­
крыв окно уже невозможно! Для прекращения ее работы восполь­
зуйтесь, к примеру, командой Stop Debugging из меню Debug.

О О становите ее!
Сделаем так, чтобы цикл, добавленный на предыдущем
шаге, останавливался при закрытии формы. Замените пер­
вую строчку на:
w h ile (V isib le )

пустите программу и щелкните на крестике в правом


верхнем углу формы. Окно закроется, и программа остано­ Подсказка: && означает
«И ». Именно эт от опера­
вится. Пусть и с задержкой в несколько миллисекунд.
т ор позволяет соединить
Ш есте несколько условий.
Проверку видимости объекта можно Результат будет ист ин­
не писать в форме — Visible == true. ным только при одновре­
Достаточно первой половины выражения. менном выполнении эт их
условии.
/
tn e .
!/
М ож ете ли вы о б ъ я сн и ть эту зад ерж ку и пер еп и сать код
та ки м образом , чтобы в о звр ащ ени е в реж им р ед акти р о ­
вания прои сходи ло сразу после закры ти я ф орм ы ?

дальше у 109
решение упражнения

ажнение Вот как должен выглядеть текст программы, циклично изменяющей фоновый цвет формы.

еш ш е
u s in g System ;
u sin g S y s te m .C o lle c tio n s.G e n e r ic ,■
u sin g S ystem .C om p on en tM od el,•
u sin g S y stem .D a ta ;
u sin g S y stem .D r a w in g ;
u s in g S y stem .L in q ; Mb/ присвоили решению имя
Fun with if Else, поэтому
u sin g S y stem .T ex t;
ИСР назвала пространство
u sin g S y stem .W in d o w s.F o r m s; имен т аким ооразом.

nam espace F u n _ w ith _ If_ E lse


{ После двойного ш,елчка на
p u b lic p a r tia l c la ss Form l : F orm кнопке ИСР добавила к ф ор­
ме метод ЬиШ т^сИскП.
{ Этот мет од запускает ­
p u b lic F o rm l0 ся при каждом ш,елчке на
{ кнопке.
In itia liz e C o m p o n e n t();
}

private void buttonl_Click(object sender, EventArgs e) Внутренний


{ оператор if
if (checkBoxl.Checked == true) проверяет
{ цвет метки.
Если мет ка
Внешний if (labell BackColor == Color.Red) красная,
оператор if { выполняется
проверяет, оператор,
labell.BackColor = Color.Blue; изменяющий
установлен
ли флажок. ' } цвет на синий.
else
{
labell.BackColor = Color.Red; Если мет ка
} не красная,
} оператор
изменяет цвет
e ls e на красный.
{
MessageBox.Show("The box is not checked")
}

} Это окно диалога появляется


при от сутст вии флажка.
С качать код с реш ени ям и всех уп р а ж н ен и й из книги
м ож но зд есь w w w .h ead firs tlab s.co m /b o o k s/h fcs h arp /

110 глава 2
это всего лишь код

Добавляя эт от мет од, ИСР поставила допол­


Построим что-то яркое!
;ненУ1е нительные пробелы перед фигурными скобками.
Иногда для экономии мест а эти скобки м огут
реш ение располагаться н й одной строке с операт о­
ром — в с * такая форма записи вполне до­
пустима.
Иногда в разделе «Решение» 1г
приводится не весь код про­ Крайне важно, чтобы ваш код могли легко чит ать
граммы^ а только те ф раг­ другие пользователи. Но мы намеренно показываем
менты, которые требовалось вам разные варианты, так как вы должны привы­
отредактировать. кнуть чит ат ь код, написанный в различном стиле.

p r iv a t e v o id b u tto n l_ C lic k (o b je c t s e n d e r, E v e n tA r g s e),

/ '" '^ w h i l e (V is ib le ) {

с = 0; с < 254 № V i s i b l e ; C++)


пока открыта
форма. t h i s . B a c k C o l o r = C o l o r . F ro m A rg b ( с , 255 - с , с );

A p p l i c a t i o n . D o E v e n ts ( ) ; ^ „г
V Ч Чиклй меняют
S y ste m .T h re a d in g .T h re a d .S le e p O );
^ в разные стороны.
}
fo r (in t с = 254; С >= О && V i s i b l e ; с--) {

t h i s . B a c k C o l o r = C o l o r . F ro m A rg b ( с , 255 - с , с );

A p p lic a tio n .D o E v e n ts О ; О п е р а т о р && п о з в о л я е т


пю ерВат ь цикл for, как
S y s t e m . T h r e a d i n g . T h r e a d . S l e e p (3) ; J^omko п а р а м е т р ViSime
^ прим ет значение false.

} П о м ни те вопрос, как уб р ать зад ер ж ку с возвращ ением


^ в реж им р ед акти ров ани я после закры тия окна?

Задержка возникает из-за невозможности проверить зна­


чение параметра Visible до завершения цикла for. Поэтому
к проверке условия добавили код && V i s i b l e .

Любую задачу программирования можно решить более чем


одним способом, так что попробуйте написать свой вариант
кода, взяв за основу циклы while вместо циклов for.
дальше ► 111
это не такой простой ребус, как кажется

Б бассейне

Возьмите фрагменты кода из бассейна


и поместите их на пустые строчки. int X = 0;
Каждый фрагмент можно исполь­ String Poem
зовать один раз. В бассейне есть
и лишние фрагменты. Нужно while (
получить программу, которая мо­
жет быть скомпилирована и за­
пущена. Имейте в виду, что задача if ( X < 1
не так проста, как кажется на первый
взгляд! }
Результат:
i f ) {

i f ( X == 1 ) {

if ( ) {
Такие задачки иногда будут встречаться
в книге. Любители логических загадок
должны их оценить. Но даже если вы
не относитесь к их числу, попробуйте
найти решение.

К а ж д ы й ф р а гм е н т
ко д а м о ж н о и с п о л ь ­
зо в а т ь то л ь ко од и н
раз!
X>0
X< 1 X=X
X> 1 X=X
X>3 X= X Poem = Poem + “noys
Poem = Poem +“ x<4 X= X Poem = Poem + “oise
Poem = Poem + “a Poem = Poem + “ oyster'
Poem = Poem + “n“; Poem = Poem + “annoys”;
MessageBox.Show(Poem);
Poem = Poem + “an“; ^ Poem = Poem + “noise”;

112 глава 2 QinBem на с. 114


это всего лишь код

аГниш ь! с КодаМи

Ну что ж, пришло время посмотреть, как же правиль­


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

е Ш е н и е ]= » е ^ с :а Б б а с с е й н е

Требовалось расположить представленные


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

in t X = 0;
S t r i n g P o em =

w h ile ( X < 4 ) {

Poem = Poem + "a";


if ( X < 1 ) {
Poem = Poem + " Результат:
}
Poem = Poem + "n";

if ( X > 1 ) {
3 noise зппо^fs ап oyster
Poem = Poem + ” oyster";

X = X + 2;
ОК 1
}
if ( X == 1 ) {

Poem = Poem + "noys

if ( X < 1 ) {
В и д и те д р у го е р е ш е н и е ?
Poem = Poem + "olse П р о в ер ь те его в И С Р
} и п о с м о тр и те , как о но
р аб о та ет!
X = X + 1;
}
MessageBox.Show(Poem);
Подсказка: Существует еще
одно решение.

114 глава 2
3 обьекш ы , 310 порядку ст|^ойс:я
%

Каждая програллма решает какую-либо проблему.


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

Ч то думает Майк о сбоих проблемах


Майк —программист в поисках новой работы. Ему не терпится показать,
как хорошо он пишет программы на С#, но сначала ему нужно попасть на
собеседование. А он опаздывает!

О АЛайк обдумы вает, каки м марш рутом лучш е поехать.

Через мост на 31-й улице,


вперед по Либерти-авеню,
а потом через Блумфилд.
Майк выбираем,
маршрут.

О Благодаря радио ДДайк узнает о большой


пробке, и з -з а которой он м о ж ет опоздать.

Это Френк Лауди с


информацией о пробках. Из-за трех
каким столкнувшихся на Либерти-авеню
ну>кио ехаиА!?- машин остановилось движение
вплоть до 32-й улицы.

О М а й к придум ы вает, как объехать пробку


и попасть на собеседование вовредля.

8 результ ат е появ­
ляется совсем другой О
Ничего, я успею
марш рут .
вовремя, если сверну
на 28-е шоссе!

116 глава 3
объекты, по порядну стройся!

Проблема Майка с точки зрения набигационной системы


Майк использует навигационную систему GPS, Диаграмма класса N avigator
которая помогает ему в перемещениях по городу. в программе Мййкй.
Вверху имя класса, SetCurrentLocationO
внизу перечислены
методы. ^ SetDestinationO
ModifyRouteToAvoidO
SetDestination("Fifth Ave & Penn Ave"); ModifyRouteTolncludeO
Резцльтат работы м е- GetRouteO
string route;
тоЪа GetRouteO - строка GetTimeToDestinationO
route = GetRoute TotalDistanceO
с марилрутом.

Навигационная
система генерирует
V
"Take 31st Street Bridge to Liberty Avenue to Bloomfield"
м арш рут , исходя из
пункта назначения.
Навигационная система
узнает, каких улиц
следует избегать. ^

\1/
ModifyRouteToAvoid("Liberty Ave");

string route;
route = GetRoute();

"Take Route 28 to the Highland Park Bridge to Washington Blvd"

^ Метод GetRouteQ прокладывает


м арш рут , исключив улицы,
цлииы.
которые Майк хочет объехать.

Навигационная система Майка решает про­


блему с прокладкой маршрута так же, как это
сделал бы он сам.
дальше ► 117
создаем методы и редактируем маршруты

Методы прокладки и редактирования маршрутов


Класс Navigator содержит методы, которые выполняют все действия. В отли­
чие от уже знакомых вам методов button_Click () они решают другую задачу:
прокладывают маршрут по городу. Именно поэтому Майк поместил эти методы
в единый класс и присвоил ему имя Navigator.
Для определения маршрута сначала вызывается метод SetDestination (), ука­
зывающий конечную точку, затем применяется метод GetRoute (), выводящий
маршрут в виде символьной строки. Если маршрут требуется изменить, на по­
мощь приходит метод ModifyRouteToAvoidO , позволяющий избежать опре­ Мйык выбирает
деленных улиц. Затем метод GetRoute {) выводит новый вариант маршрута. для методов
значимые имена.
class Navigator {

public void SetCurrentLocation(string locationName) {

ptiblic void SetDestination (string destinationName) { , };


public void ModifyRouteToAvoid(string streetName) { ... };

public (string GetRoute 0 { ... };

string route =
GetRoute {);
вм вровде« 3 „ „ e"L ,

Методы, возвращающие значение Вот пример метода,


возвращающего ^
Методы состоят из операторов. Некоторые из них выполняют все входя­ значение типа int.
Метод использует
щие операторы и заканчивают работу. Другие же в о з в р а щ а ю т к а к о е-т о два параметра
з н а ч е н и е . Это значение принадлежит к определенному типу (например, для вычисления
s t r i n g или i n t ) . результ ат а,
а зат ем при помощи
О ператор r e t u r n прерывает работу метода. Если метод не возвращает оператора return
значения, тип возвращаемого значения объявляется как v o id , присут­ передает значение
ствие этого оператора является необязательным. Но если метод возвра- X вызвавилему его
щает значение, без оператора r e t u r n не обойтись. i / оператору

p u b lic in t M u ltip ly T w o N u m b er s(in t firstN u m b er, in t secondN um ber) {


in t r esu lt = firstN u m b er * secondN um ber;
retu rn r e su lt;

Оператор вызывает метод, перемножающий два числа. Возвращаемое


значение принадлежит к типу int: В м етоЭь! м ож но
п о д с т а в л я т )^ не
in t m y R e su lt = M u ltip ly T w o N u m b er s(3, 5); ' только константы,
но 1А перем еним .
118 глава 3
объекты, по порядку стройся!

КЛЮЧЕВЫЕ
МОМЕНТЫ
Классы состоят из методов, которые, в свою очередь, состоят из операторов. Осмысленный выбор методов позво­
ляет получить удобный для работы класс.
Некоторые методы могут возвращать значение. Тип этого значения нужно объявлять. Например, метод, объявлен­
ный как public int, возвращает целое число. Пример такого оператора: return 37 ;
Метод, возвращающий значение, обязан включать в себя оператор return. Если в объявлении метода указано
public string, значит, оператор return возвращает значение типа string.

После оператора return программа возвращает управление оператору, вызывающему метод.

Метод, при объявлении которого было указано public void, не возвращает значения. Но оператор return
может использоваться для прерывания такого метода: if (finishedEarly) { return; }.

Построим программу с использованием классоб


Привяжем форму к классу и сделаем так, чтобы принадлежащая фор­
ф
ме кнопка вызывала метод этого класса. араж нение

^ Создайте новый проект Windows Forms Application. В окне Solution Explorer щелкни­
те правой кнопкой мыщи на имени проекта и вы берите в появившемся меню команду
A dd»C lass... Н азовите файл Talker.cs, при этом класс автоматически получит имя
Talker. В ИСР появится новая вкладка с именем Talker.cs.

Сверху вставьте строчку using System.Windows .Forms, a затем введите код самого класса:
class Talker {
p u b lic s ta tic i n t B la h B la h B la h (s tr in g th in g T o S a y , i n t n u m b e r O fT im e s )
{
О перат ор s tr in g f in a lS tr in g =
о5т?я6ляет
кхеременнуи? fo r ( i n t c o u n t = 1; c o u n t <= numberOf T im e s; co u n t+ + )
finalString { X
и пры соаийа fin a lS tr in g = fin a lS tr in g + t h i n g T o S a y + " \n " \
t m ей нулевое ^
К переменной FinalString
c m y ^ C w p o K y )- M e s s a g e B o x .S h o w (fin a lS tr in g ) ;
добавляется значение
r e tu r n fin a lS t r in g .L e n g t h ; , переменной thingToSay и знак
1
} Метод BlahBlahBlahQ возвращает
^ переноса строки (\п).
значения типа int. Свойство .Length ^ Свойством Length
можно добавить к любой строке обладают все строки.
и узнать ее длину. Знак переноса (\п)
считается за один
символ.

IJej^eBepHuiue с тр ан и ц у и и родолж ш !

дальше ► 119
знакомство с объектами

*
Ч то )ке мы только что построили?
Новый класс содержит метод с именем B l a h B l a h B l a h {) и двумя параметрами. Первый пара­
метр — строка с произносимым текстом, а второй — количество повторений. Этот метод вы­
зывает окно, в котором фраза повторяется указанное количество раз. Метод возвращает дли­
ну строки. Ему следует передать строку для параметра t h i n g T o S a y и число для параметра
n u m b e r O f T i m e s . Указанные значения вводятся в поля формы, созданные на основе элементов
управления T e x t B o x и N u m e r ic U p D o w n .
Добавим в проект форму, работающую с новым классом!
О т редакт ируйте свойство
Text таким образом, ч т о ­
бы в текстовом поле по
умолчанию появлялся т екст Saythis: Hello!
«Hello!» # oftimes: 3

О Вот внешний вид формы.


Дважды щелкните на кнопке, чтобы добавить к ней код, вызывающий метод B l a h B l a h B l a h ( ) / .
Он должен возвращать целое число 1еп: Свойству M inimum
<^рисвойте значение и,
p r iv a te v o id b u tto n l_ C lick (o b ject sen d er, E ven tA rgs e) a с в о ^ т в ^ ^ а ^ е '^ :^ ^ ^ "

i n t l e n = T a l k e r .B la h B la h B la h ( t e x t B o x l.T e x t, (in t)n u m e r ic U p D o w n l.V a lu e );


M e s sa g e B o x .S h o w (" T h e m e s s a g e l e n g t h i s " + l e n ) ;

Запустите программу! После щелчка на кнопке вы увидите


два окна с текстом. Класс вызывает первое окно, ф орма —
второе.
ШШ Возвраи^енное
ШШ
Метод BlahBlahBlahQ вы­
методом
зывает окно с сообш,ением,
сформированным на основе значение форма T h e m e s s a g e le n g th is 21
НеКо!
введенных пользователем Не«Ы
показывает
Hello! в эт ом окне
параметров. диалога. \ /
f Ш 1

...... ......

Методы добавленного к проекту оасса можно


использовать и в других классах.
120 глава 3
объекты, по порядку стройся!

ІІдея Майка Вот если бы сравнить


несколько маршрутов и выбрать
Собеседование прошло замечательно! из них самый быстрый...
Но утренние пробки заставили Майка за­
думаться об усовершенствовании его на­
вигационной программы.

Почему бы не создать три класса Navigator...


Майк м о ж ет скопировать код класса N a v i g a t o r и вставить его Э т о диаграмма классов.
в другие классы. В результате программа получит возможность В ней перечисляются
одновременно сохранять три маршрута. все 6кодяш,ие в класс
методы. Это наглядное
представление
выполняемых классом
N a v ig a to r функций. .
SetDestinationO N a v ig a to r2
ModifyRouteToAvoidO
ModifyRouteTolncludeO SetDestinationO
N a v ig a to rs
GetRouteO ModifyRouteToAvoidO
ModifyRouteTolncludeO SetDestinationO
GetTimeToDestinationO
GetRouteO ModifyRouteToAvoidO
TotalDistanceO
GetTimeToDestinationO ModifyRouteTolncludeO
TotalDistanceO GetRouteO
GetTimeToDestinationO
TotalDistanceO

Получается, что редактировать


О ( метод теперь придется три раза
вместо одного?

И м енно так! У прав л ение тр ем я копиям и одного кода — непро стая за д а ­


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

дальше ► 121
про экземпляры

Объекты как способ решения проблемы


Объектами (objects) называются инструменты С#, позволя­
ющие работать с набором одинаковых сущностей. Именно
благодаря им, один раз написав класс N a v i g a t o r , Майк смо­
жет использовать его нужное количество раз.

N a v ig a to r
3 « « . « SetCurrentLocationO
W3 C^WCKOM SetDestinationO
ModifyRouteToAvoidO
дде1ляоЭоб.' ModifyRouteTolncludeO
GetRouteO
GetTimeToDestinationO
TotalDistanceO

' Для сравнения


т рех марилрутов
Майк воспользу-
i# ^ ется т ремя о6г>-
актами Navigator.
Д л я создани я об ъ екта д остато чн о
клю чевого слова new и им ени класса.

Navigator navigatorl = m e v y Navigator () ;


navigatorl.SetDestination("Fifth Ave & Penn Ave");
string route;
route = < g a ]^ g a ^ o rl. GetRouteTT

О б ъ ект уж е м ож но использовать! Так как


он получен из кл асса, то сод ер ж и т все
вход и в ш ие в кл асс методы .

122 глава 3
объекты, по порядку стройся!

Возьмите класс и постройте объект


Класс можно представить как копию объекта. Скажем, для по­
строения пяти одинаковых домов в коттеджном поселке архи­
тектору не нужно рисовать пять одинаковых чертежей. Для вы­
полнения задачи вполне достаточно одного.

Определяя класс, вы определяете


и его методы, точно также как
чертеж определяет внешний вид
дома. '

На основе одного чертежа


Можно построить сколько
угодно домов, а из одного
класса можно получить
сколько угодно объектов.

Объект берет методы из класса


Оператор new позволяет создать произвольное количество объ­
ектов одного класса. При этом все методы исходного класса ста­
новятся частью объекта.

Дом
ДатьКровО
ВыраститьЛужайкуО
ДоставитьПочтуО
ПочиститьКанализациюО
ЗаплатитьНалогО
СделатьРемонтО

дальше > 123


объекты совершенствуют ваш код

Экземпляры
Все элементы окна Toolbox являются классами: класс B u t t o n ,
класс T e x t B o x , класс L a b e l и т. п. При перетаскивании
на форму кнопки из окна Toolbox автоматически создает­
ся экземпляр класса B u t t o n , которому присваивается имя
b u t t o n l . Перетаскивание второй кнопки приводит к появле­
нию второго экземпляра с именем b u t t o n 2 . Каждый экзем­
пляр имеет собственные свойства и методы. Но при этом все
кнопки работают одинаково, так как они были созданы из од­
ного класса.

До: Так выглядим памят ь


компьютера перед началом
работы программы.

' ^выполняется
/ ^<^ератор new.

Ho u s e m a p l e D r i v e l l S = n e w H o u s e ();

^"^У п р> аж н ен и е
Убедитесь сами!
Откройте любой проект, в котором присутству­
ет кнопка b u t t o n l , и найдите в его коде текст
b u t t o n l = new. Этот код ИСР добавила в кон­
Экземпляр,
структор форм при создании экземпляра класса образец, вещь, подобная
B u tton . другим, функция поиска и заме­
ны находит все экземпляры слова
и заменяет их.

124 глава 3
объекты, по порядку стройся!

Простое решение! с и / -- это сокращение от


graphical User Interface
Майк придумал новую программу сравнения маршрутов, ко­ {^р^сричсский иии/\срфсис
торая ищет кратчайший путь при помощи объектов. Вот как пользователя).
она создавалась.

Майк добавил к СТЛ текстовое поле — ЪехЬВох!, содержащее информацию о пункте назна­
чения. Затем создал поле te x tB o x 2 , для ввода названия улицы, которую нельзя включать
в маршрут; и поле ЬехЬВохЗ, содержащее информацию о еще одной улице, которую жела­
тельно объехать.

Это экземпляр
© О н со зд а л о б ъ е к т N a v i g a t o r и указал пункт н а зн а ч ен и я . класса Navigator.

N a v ig a to r
SetCurrentLocationO
SetDestinationO
IVIodifyRouteToAvoidO
str in g d e stin a tio n = te x tB o x l.T ex t;
!\/1odifyRouteTolnclude()
GetRouteO N a v ig a to r n a v i g a t o r l = n e w N a v i g a t o r () ;
GetTimeToDestinationO
TotalDistanceO n a v ig a to r l. S e t D e s t i n a t i o n ( d e s t i n a t i o n ) ;

ro u te = n a v i g a t o r l . G e t R o u t e () ;

O h добавил второй объект N a v ig a t o r с им енем n a v ig a t o r 2


и вы звал м е т о д S e t D e s t i n a t i o n O э т о г о о б ъ ек т а для зада­
н и я пункта н а з н а ч ен и я , п о с л е ч е г о вы звал м е т о д M o d i f y ­
R o u t e T o A v o i d () ( Р е д а к т и р о в а т ь и з б е г а е м ы е у л и ц ы ) .

Третий объект N a v i g a t o r называется n a v i g a t o r s . Майк указал „ „ М string-


пункт назначения и вызвал метод M o d i f y R o u t e T o l n c l u d e O
(Редактировать включаемые в маршрут улицы) J

vigotorl'
5,6 км Создание нового
объекта на основе
класса называется
Теперь Майк может вызвать общий для всех объектов метод
T o t a l D i s t a n c e O (Общее расстояние) и определить самый
созданием экзем­
короткий маршрут. И для этого ему понадобился один фраг­ пляра класса.
мент кода, а не три!

дальше У 125
немножко маленьких секретов

Эй, подождите-ка! Данной вами


информации недостаточно для того,
чтобы написать навигационную
программу!

Э т о д е й с т в и т е л ь н о т а к . Программа построения маршрутов очень


сложна. Но сложные программы работают по тому же принципу, что
и простые. Навигационную программу Майка мы привели только
как пример использования объектов на практике.

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

Ho u s e m a p l e D r i v e l l S = n e w Ho u s e О ;

Знакомясь с новыми понятиями


(например, с объектами), вни­
мательно смот рит е на кар­
тинки и код.

У вас будет достаточно возможностей применить полученные знания


на практике. Иногда это выполнение письменных упражнений, одно
из которых вы найдете на следуюш,ей странице. В других случаях вам Если у вас слож­
сразу будет предложено написать код. Такая комбинации теории с
практикой является самым эффективным способом запоминания но­ ности с выполне­
вой информации.
нием упражнения,
Упра)княясь В написании кодов...
...желательно помнить следуюш;ее: можно сразу по­
★ Сделать опечатку очень легко. При этом даже одна незакрытая
скобка является препятствием к построению программы.
смотреть решение.
★ Лучше подсмотреть решение, чем долго мучиться. Мучения от­ Его можно даже
бивают желание учиться.
★ Код, который вы найдете в этой книге, протестирован и рабо­ скачать с сайта
тает в Visual Studio 2010! Но от опечаток никто не застрахован
(можно перепутать 1 и букву L нижнего регистра). Head first Labs.
126 глава 3
объекты, по порядку стройся!

Г в руку карандаш
Попробуйте вслед за Майком написать код для объектов
N a v i g a t o r И вызова ИХ
методов.

str in g d e stin a tio n = te x tB o x l.T e x t;


Здесь Майк задавал пункт
str in g r o u te 2 S tre e tT o A v o id = tex tB o x 2 .T ex t; назначения и улицы,
str in g r o u te 3 S tr e e tT o In c lu d e = tex tB o x 3 .T ex t; которых следует избегать.

N a v ig a to r n a v ig a to r l = new N a v i g a t o r ( ) ; А здесь MW создаем объект


n a v ig a to r l.S e tD e stin a tio n (d e stin a tio n ); n a v i g a t o r , указываем п у н к т
in t d ista n ce l = n a v ig a t o r l.T o t a lD is t a n c e {);
назначения и определяем
расстояние.

. Создайте объект navigator2, укажите пункт назначения, вызовите метод ModifyRouteToAvoidO,'^


а затем воспользуйтесь методом TotalDistanceO для вычисления переменной distance2.

Navigator navigator2 =

navigator2.

navigator2.

int distance2 =

^2.CoздaйтeoбъeктnavigatorЗ,yкaжитeпyнктнaзнaчeния,вызoвитeмeтoд^ЯodifyRouteToincludeO,~*
a затем воспользуйтесь методом TotalDistanceO ДЛЯ вычисления целой переменной distances.

L _
Встроенный в .NET Framework метод Math.MmQ
сравнивает два числа и возвращает меньшее. Именно
с его помощью Майк нашел самый короткий путь.

in t sh o r te stD ista n c e = M a th .M in (d is ta n c e l, M a th .M in (d is ta n c e s, d ista n ce s ));

дальше > 127


слово static

|Лозьми В руку карандаш


п Вот как правильно создать объекты N a v i g a t o r и вызвать их
6Ш6НИ6 методы.

str in g d e stin a tio n = te x tB o x l .T e x t; Зд есь И айк задавал


str in g r o u te 2 S tre e tT o A v o id = te x tB o x 2 .T e x t; н азн ач ен и я
^ \ M улицы , кот оры х
str in g r o u te S S tr ee tT o In clu d e = tex tB o x 3 . T e x t; j сл ед ует и зб ега т ь.

N a v ig a to r n a v ig a to r l = n e w N a v i g a t o r () ; ^ ^ СОзЭаеМ о б ш к т
n a v ig a to r l. S e tD e stin a tio n (d e stin a tio n ) ; ^ a .v ig a t o r , у к а з ы в а е м п у н к т
in t d ista n ce l = n a v ig a to r l .T o ta lD ista n c e 0 ; ^ н а з н а ч е н и я и определяем
расст ояни е.

1. Создайте объект navigator2, укажите пункт назначения, вызовите метод ModifyRouteToAvoidO,


а затем воспользуйтесь методом TotalDistanceO Для вычисления переменной distance2.

Navigator navigator2 = new NaviyatorQ

navigator2 . SetDestination(destination);

navigator2 . ModifyRouteToAvoid(routeZStreetToAvoid);

int distance2 = navigatorZ.TotalDi$tanceQ;

*~2.CoздaйтeoбъeктnavlgatorЗ,yкaжитeпyнкт назначения, вызовитеметод ModifyRouteTolncludeO,"^


a затем воспользуйтесь методом TotalDistanceO для вычисления переменной distances.

navigator3.SetDestination(destination);

navigator5.ModifyRouteTolnc!ude(route3StreetTolnclude);

int distances = navigators.TotalDistanceQ;

Встроенный 6 .NET Framework метод Matk.MinQ


сравнивает два числа и возвраш,ает меньшее.
Именно с его помощью Майк нашел самый
короткий путь.
in t sh o r te stD ista n c e = M a th .M in (d is ta n c e l, M a th .M in ( d i s t a n c e s , d ista n ce s))

128 глава 3
объекты, по порядку стройся!

Я написал уже несколько новых классов, но ни разу


не воспользовался ключевым словом new! Получается,
О я могу вызывать методы, не создавая объектов?

Д а! И и м енно поэтом у в м етодах и споль зов алось клю чевое сл о во s t a t i c .


Еще раз посмотрим на объявление класса T a lk e r:
c la ss T a lk er
{
p u b lic sta tic in t B la h B la h B la h (strin g th in g T o S a y , in t n u m b erO fT im es)
{
str in g fin a lS tr in g =

П ри вызове метода не создавался новы й экземпляр T a lk e r. Вы написали только:


T a lk e r.B la h B la h B la h (" H e llo h e l l o h e llo " , 5);

Именно так вызываются с т а т и ч е с к и е методы, с которыми вы работали до сих пор.


Если убрать модификатор s t a t i c из объявления метода B l a h B l a h B l a h (), вызов
метода окажется уже невозможен без создания экземпляра T a l k e r . Впрочем, это
единственное отличие статических методов. Вы можете передавать им параметры,
они возвращают значения и принадлежат определенным классам.
Модификатором s t a t i c можно отметить целы й класс. Все входящие в этот класс
методы также долж ны бы ть с т а т и ч е с к и м и . Добавив в статический класс нестати­
ческий метод, вы сделаете компиляцию невозможной.

Чаап°
'^ а Д а Б а е М ы е
Б о гц р о с ь і

Слово «статический» ассоциируется у меня с веща­ Почему не сделать статическими все методы?
ми, которые не меняются. Означает ли это, что нестати­
ческие методы могут меняться, а статические нет? 0 1 При наличии объектов, отслеживающих данные, напри­
мер, экземпляров класса N a v i g a t o r , каждый из которых
0 ; Нет. Единственным отличием статического метода от отслеживал свой маршрут, для работы с этими данными мож­
нестатического является невозможность создавать его эк­ но использовать собственные методы экземпляра. Скажем,
земпляры. Слово «статический» в данном случае не следует при вызове метода M o d i f y R o u t e T o A v o i d () для экзем­
воспринимать слишком буквально. пляра n a v i g a t o r s менялся только маршрут номер два.
На маршруты экземпляров n a v i g a t o r l и n a v i g a t o r s
То есть я не смогу пользоваться классом, не создав эта процедура никак не влияла. Именно поэтому программа
экземпляр объекта? Майка могла работать с тремя маршрутами одновременно.

0 ; Создание экземпляров является обязательным услови­ • А как именно экземпляры отслеживают данные?

О
ем для работы с нестатическими классами. Для статических
классов это не требуется. ; Переверните страницу и узнаете!

дальше * 129
как дела у объектов

Поля
Редактирование расположенного текста на кнопке осуществляет­
ся при помощи свойства T e x t . При внесении подобных измене­ Технически вы
ний в конструктор добавляется следующий код: задаете свойстЯп
Свойс\тва очень
b u tto n l.T e x t = "Текст для кнопки";
покожи на поля^
Как вы уже знаете, b u t t o n l —это экземпляр класса B u t t o n . ' Код но об эт ом мы
же редактирует поле этого экземпляра. На диаграмме классов спи­ поговорим чуть
позже.
сок полей находится сверху, а список методов —снизу.

Сверху на диаграмме
классов находится список
полей. Экземпляры
класса используют их Эта линия
для отслеживания своего отделяет поля
состояния. от методов.

Метод — это то, что объект делает. Поле — это то, что объект знает^.
в результате создания Майком трех экземпляров класса N a v i g a t o r его программа создала три
объекта, каждый из которых отслеживает свой маршрут. При вызове метода S e t D e s t i n a t i o n ()
для экземпляра n a v i g a t o r 2 пункт назначения указывается только для этого экземпляра. Он ни­
как не влияет на экземпляры n a v i g a t o r l и n a v i g a t o r 3 .

N a v ig a to r Каждый из экземпляров
Navigator знает свой пункт
Destination назначения и свой маршрут.
Route

SetCurrentLocationO Объект Navigator позволяет


SetDestinationO указывать пункт назначения,
ModifyRouteToAvoidO
редактировать возможный
марш рут и получать
ModifyRouteTolncludeO информацию об эт ом
GetRouteO маршруте.
GetTimeToDestinationO
TotalDistanceO
Поведение объекта определяется его
методами, поля используются для от­
слеживания его состояния.
130 глава 3
объекты, по порядку стройся!

Создаем эЬемкдяры!
M em odL
Для добавления полей достаточно объявить I
п е р е м е н н ы е в н е м е т о д о в . Так, в с е эк зем п л я - c l a s s C lo w n {
ры будут и м ет ь с в о и к о п и и э т и х п е р е м е н н ы х . str in g Nam e;

p u b lic in t H eig h t;

p u b lic v o id T a l k A b o u t Y o u r s e l f () {
M e s s a g e B o x . S h o w ( "My n a m e is "
+ Nam e + " and I'm "
+ H eig h t + " in c h e s ta ll." );

При создании экземпляра,


не использиймя ключевое Операт ор *= означает,, что
слово static ни в объявленш парамет р, стояиА,ий справа от
класса, ни в объявлении /" оператора, нужно умножить
метода. на парамет р, стоящий слева.
м/
^Возьми в руку карандаш
Клоуны рассказывают о себе при помощи метода
Та1кАЬои1Уоигзб1^ Они называют имя и рост. Напишите,
какие сообщения будут содержать всплывающие окна.
C lo w n o n eC lo w n = new C lo w n ( );
o n e C lo w n .N a m e = " B offo" ;

o n e C lo w n .H e ig h t = 14;

o n e C lo w n .T a l k A b o u t Y o u r s e l f ( ) ; «Меня зовут , мои рост .дюймов»

C lo w n a n o th er C lo w n = new C lo w n ();

a n o th e r C lo w n .N a m e = " B iff" ;
a n o th e r C lo w n .H e ig h t = 16;

a n o t h e r C lo w n .T a lk A b o u t Y o u r s e lf ( ) ; «Меня зовут. , мои рост .дюймов»

C lo w n c lo w n s = new C lo w n {);

c lo w n 3 .N a m e = a n o th e r C lo w n .N a m e ;

c lo w n 3 .H e ig h t = o n e C lo w n .H e ig h t - 3^

c l o w n 3 .T a l k A b o u t Y o u r s e l f () ; «Меня зовут , мой рост .дюймов»

a n o th e r C lo w n .H e ig h t *= 2;

a n o t h e r C lo w n .T a lk A b o u t Y o u r s e lf 0 ; «Меня зовут , мои рост. дюймов»

дальше > 131


складываем объекты в кучу

Спасибо за память
Создаваемые объекты находятся в так называемой куче
(heap) — области динамической памяти, выделяемой на
стадии исполнения программы. Применение оператора
new автоматически резервирует место в памяти под хра­
нение данных. /
Вот так выглядит куча до
начала работы программы.
Д д, она действительно
пуста.

Внимательно посмотрим на происходяи^ее здесь

Решение Вот как нужно было заполнить пробелы в тексте.

Операторы jjew создают


C lo w n o n eC lo w n S ^ ^ ew C l o w n () экземпляр?« класса Clown,
резервируя участки памяти и
o n e C lo w n .N a m e = " B S tfn - заполняя их данными об объекте
o n e C lo w n .H e ig h t = 14;

o n e C lo w n .T a l k A b o u t Y o u r s e l f () ; «Меня зовут Boffo , мой рост 3-4 дюймов^

C lo w n a n o th er C lo w n = (n ew C lo w n ( );

a n o th e r C lo w n .N a m e = " B iff" T
a n o th e r C lo w n .H e ig h t = 16;

a n o t h e r C lo w n .T a lk A b o u t Y o u r s e lf 0 ; «Меня зовут Biff , мой рост дю йм ову

--- - .
C lo w n c lo w n 3 = m ew C lo w n () ;
c lo w n B .N a m e = an o B H S F C T o ra .N a m e;

c lo w n 3 .H e ig h t = o n e C lo w n .H e ig h t - 3;

c l o w n 3 .T a l k A b o u t Y o u r s e l f ( ) ; «Меня зовут Biff _ мой рост 3-3- дюймов»

a n o th e r C lo w n .H e ig h t *= 2;

a n o t h e r C lo w n .T a lk A b o u t Y o u r s e lf ( ) ; «Меня зовут Biff . мой РОСТ S 2 дюйма».

Новые объекты добавляются в кучу — динамически рас


пределяемую память.
132 глава 3
объекты, по порядку стройся!
Это экземпляр
Ч то происходит 6 памяти программы класса Clown.

Программа создает новый экземпляр класса C low n :

C lo w n m y l n s t a n c e = new C lo w n ( );

В выражении использованы два оператора. Пер­


вый объявляет переменную типа C l o w n ( C l o w n
m y l n s t a n c e ; ) . Второй создает новый объект и
присваивает его только что созданной переменной
(m y ln sta n ce = n e w C l o w n О ; ) . Вот как выглядит
куча после выполнения каждого из операторов:

C lo w n o n eC lo w n = new C lo w n о
o n e C lo w n .N a m e = " B offo" ;
^Ьект
o n e C lo w n . H e ig h t = 14; vvOA^-
o n e C lo w n .T a lk A b o u tY o u r s e lf();

C lo w n a n o th er C lo w n = new C l o w n ()
a n o th e r C lo w n .N a m e = " B iff" ;
Операторы
создают второй
a n o th e r C lo w n .H e ig h t = 16; объект и п р и ­
' • a n o t h e r C l o w n . T a l k A b o u t Y o u r s e l f {)
сваивают ему
данные.

о C lo w n c lo w n 3

c lo w n 3 .N a m e
= new C lo w n 0 ;

= a n o th e r C lo w n .N a m e ;
c lo w n 3 .H e ig h t = o n e C lo w n .H e ig h t - 3
-c lo w n s.T a lk A b o u tY o u rself();

a n o th erC lo w n .H eig h t *= 2;

■ ' a n o t h e r C l o w n . T a l k A b o u t Y o u r s e l f () ;

Так как команда n e w н е


используется, новый объ­
ект не создается. Редак­
т ирует ся только и н­
формация, которая уже ^
имеется о памяти.

дальше > 133


зачем нужны методы

Значимые имена
При написании кода методов выбирается структура программы. Вы ищете
ответы на вопросы: воспользоваться ли одним методом или, может быть,
разбить его на несколько? А может быть, метод тут вообще не нужен? В ре­
зультате можно получить как интуитивно понятный код, так и нечто за­
путанное и нечитаемое.

О Перед вами пример компактного кода. Это программа, управляющая автоматом по производ-
ству шоколадных батончиков.

іпЬ t = т.сЬкТетр( ч^сло... но дляцелое


tb, т — а {t > 160) { чего?
ужасные имена! Т tb = пеш
Вы никогда не Метод с1&Тгр\'() имеет
ЬЬ.с1зТгр\/((2
догадаетесь, ---- один П(Хр(ХМС\Л/\.р} но
І С 8 . Р ІП () ; б жызнм не угадаете его
зачем нужны эти
переменные и ic s.V e n t О ; предназначение.
какова функция .т.аігзузсЬкО
класса Т.

Вы можете, в зглянув на этот код, понять, какую ф ункци ю он в ы полняет?

© Операторы не дают даже намеков на предназначение кода. Зато нужный результат полу­
чен при помощи всего одного метода. Но всегда ли максимальная компактность является
конечной целью? Давайте разобьем код на несколько методов и сделаем его более про­
стым. Вы на практике убедитесь в необходимости классов и осмысленных имен. Для на­
чала нужно понять, какую задачу решает данный код.

Управление автоматом, производящим батончики


Автоматизированная система проверяет температуру
нуги каждые 3 минуты. Если она выше 160 °С, необхо­
димо выполнить процедуру охлаждения (С1С8).
• З а к р ой т е клапан турби ны #2
• Зап ом ни те водой систему охлаж дения

• В ы п устите воду

• У беди тесь, ч то в с и с т е м е отсутствует воздух

134 глава 3
объекты, по порядку стройся!
О Инструкция не только помогла определить назначение кода, но и показала, как сделать его
более понятным. Мы узнали, что проверка условия определяет, не превышает ли параметр
Ъ значение 160, ведь в инструкции написано, что при 160 °С нуга становится слишком го­
рячей. А буква т оказалась классом, который контролирует поведение автомата. В класс
входит статический метод проверки температуры нуги и работы воздушной системы. Вы­
делим проверку температуры в отдельный метод и дадим классу и методу смысловые имена.

' p u b l T c ^ ' b o o l e a ^ I s N o u g a t T o o H o t {) {
Тип значений, in t tem p = M aker. C h eck N ou gatT em p eratu re{);
возвращ аем ы х (tem p > 160) { ^ Назовем к л а с с M a k e r
^ r e t u „ t.ue,. L

j , , , ^ 3 ^ наг«).

, ^ В о зв р а щ а е м ы е зн ач ен и я
J т и п а B o o le a n , э т о tr u e
и л и fa lse .

При превышении рекомендуемой температуры инструкция требует выполнения процеду­


ры CICS. Создадим еще один метод и выберем для класса Т (он управляет турбиной) более
значимое имя. Переименуем также класс i c s (управляющий изолированной системой ох­
лаждения). Этот класс содержит два статических метода. Один —для заполнения системы
водой (fill), второй —для слива воды (vent):

p u b l i c (y o i d J P o C I C S V e n t P r o c e d u r e () {

/к о д и ф и к а т о р v o id T u r b in e tu r b in e C o n tr o lle r = new T u r b i n e () ;
озн ач ает , чт о м ет о д t u r b i n e C o n t r o l l e r . C lo se T r ip V a lv e (2) ;
Т н а ч е н т '^ ^ ^ '^ ни как ого I s o l a t i o n C o o l i n g S y s t e m . F i l l {) ;
Is o la tio n C o o lin g S y ste m .V ent О ;
M a k e r .C h e c k A ir S y ste m O ;

}
Теперь, даже если вы не читали инструкцию и не знаете, что процедура CICS запускается
при слишком высокой температуре нуги, вы все равно можете понять, что делает код:
if { I S N o u g a t T o o H o t () == tru e) {
D oC IC S V en tP roced u re( ) ;

Помните 0 T O M , зачем вы пишете код. Это позволит сделать ко­


нечный результат простым и легко редактируемым. Выбор смыс­
ловых имен упрощает последующую расшифровку программы
другими людьми и дает возможность улучшить код!
дальше > 135
классы как они есть

Структура классоб
Почему же методы следует делать интуитивно понятными? Потому что каждая
программа решает проблему или имеет конкретную цель. Целью далеко не
всегда являются серьезные задачи, иногда программы могут писаться просто для
забавы! Но каково бы не было предназначение программы, чем больше код напо­
минает о том, какая именно проблема с его помош;ью решается, тем проще такую
программу писать, читать и редактировать.

Д и а гр а м м а к л а с с а
C la s s N a m e
Э т о н а гл я д н о е п р е д с т а в л е н и е MethodO
к л а с с а на л и с т е дуллаги. MethodO
MethodO
В в е т ц п и ш е т с я амя к л а с с а ,
а п о д н и м в се в х о д я щ и е
в класс м ет оды !

Пример построения диаграммы


Посмотрите на оператор 1 £ из пункта #5 на предыдущей странице. Вы уже знаете,
что операторы находятся внутри методов, а методы, в свою очередь, внутри клас­
сов? В данном случае оператор i f принадлежит методу D o M a in te n a n c e T e sts {),
который является частью класса С а п с 1 у С о п Ь г о 1 1 е г . Теперь разберемся, как со­
относятся друг с другом код и диаграмма классов.

c la ss C a n d y C o n tro ller {

p u b lic v o id D o M a i n t e n a n c e T e s t s () {

if ( I S N o u g a t T o o H o t () == tru e) {
D oC IC S V en tP roced u re(); C a n d y C o n tro lle r
} DoMaintenanceTestsO
DoCICSVentProcedureO
} IsNougatTooHotO

p u b lic v o id D o C I C S V e n t P r o c e d u r e ()

p u b lic b o o le a n I S N o u g a t T o o H o t {) ..

136 глава 3
объекты, по порядку стройся!

возьми в руку карандаш


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

“»І»

Ж "
ддетоЭ.

Программа содержит

м °m Z “

дальше ¥ 137
несколько советов

Выбор структуры класса при помои^и


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

П осудом ойка П осудом ойка


МытьеТарелокО Все методы класса МытьеТарелокО
ДобавкаМылаО «П осудом ойка» должны бы ть ДобавкаМылаО
ТемператураВодыО связаны с мы тьем посуды . ТемператураВодыО
ПарковкаМашины()
с этой процедурой ни как не
связан, поэтом у его нуж но
пом естить в д ругой класс.

_________________

Возьми в руку карандаш


^0ШеНИ6 должны выглядеть диаграммы клас- Понять, что Maker —
сов, которые вам было предложено запел- название класса, легко
нить на предыдущей странице. положению 6 имени
Maker.CheckAirSystemQ.

Turbine IsolationC oolingSystem M aker


FillQ
CloseTripValveQ C keckN o u g a tT em p era tu reQ
VentQ
C heckA irSystem Q

138 глава 3
объекты, по порядку стройся!

_ і^озьм и в руку карандаш


Все эти классы содержат ошибки. Напишите, в чем, по ва­
шему мнению, они состоят, и как их можно исправить.

Класс23 Этот класс является частью знакомой вам системы произ­


водства шоколадных батончиков.
ВесБатончикаО
ПечатьОберткиО
ПечатьОтчетаО
ДелаемО

Р азносчи кП и ц цы
Эти классы являются частью системы учета доставки пиццы.
ДобавитьПиццуО
ПиццаДоставленаО
ПодсчетСуммыО
ВремяВозвращенияО
Р а зн о с ч и ц а П и ц ц ы
ДобавитьПиццуО
ПиццаДоставленаО
ПодсчетСуммыО
ВремяВозвращенияО

Класс КассовыйАппарат является частью программы


Кассовы йА ппарат автоматизированной системы контроля в круглосуточном
ПродажиО магазине.
НетПродажО
ЗакачатьГазО
ВозвратДенегО
ВсегоВКассеО
СписокТранзакцийО
ДобавитьСуммуО
ВычестьСуммуО

дальше * 139
создадим класс

Возьми в руку карандаш


В от как мы ско р р екти р о в ал и классы . Но это лишь один
Решение способ решения проблемы. Можно использовать и другие спо­
собы, в зависимости от того, как предполагается использовать
класс.

V
Этот класс является частью знакомой вам системы
производства шоколадных батончиков. Д елаем Б атончики
Из имени класса С1а5523.ао() не понятно его назначение. ВесБатончикаО
ПечатьОберткиО
Кроме того, мы выбрали более осмысленное имя для ПечатьОтчетаО
СоздатьБатончикО
последнего метода.

Эти классы являются частью системы учета доставки пиццы.


Р азносчикП иццы
Классы Pe^(Very^5uy и РеИуегур 1'Н выполняли одну
Пол
задачу. Имеет смысл объединить их друг с другом,
ДобавитьПиццуО
добавив поле для ввода половой принадлежности ПиццаДоставленаО
ПодсчетСуммыО
работника. ВремяВозвращенияО

Поле Пол было добавлено,


чтобы отслеживать
результат ы работы юношей
и девушек по отдельности.

Класс КассовыйАппарат является частью программы


автоматизированной системы контроля круглосуточного Кассовы йА ппара!
магазина. ПродажиО
был удален метод ЗакачатьГаз(), как единственный, НетПродажО
ВозвратДенегО
не имеющий отношения к работе кассовых ВсегоВКассеО
СписокТранзакцийО
аппаратов. ДобавитьСуммуО
ВычестьСуммуО

140 глава 3
объекты, по порядку стройся!

p u b lic p a r tia l c la s s Form l : Form


(
p r iv a te v o id b u tto n l_ C lic k (o b je c t sender, E v en tA rg s e)
{
S tr in g r esu lt =

Echo e l = new E c h o ( ) ; Возьмите фрагменты кода из бас­


сейна и поместите их на пустые
строчки. Фрагменты можно
in t X = 0; использовать несколько раз.
w h ile { ) { В бассейне есть и лишние
фрагменты. Полученная в ито­
resu lt = resu lt + e l.H e llo 0 + " \n " ;
ге программа должна выводить
окно с показанным ниже текстом.
if ) {
e 2 . c o u n t = e 2 . c o u n t + 1; Результат:
}
if { ________________ ) {
e 2 .c o u n t = e 2 .c o u n t + e l.c o u n t ;
НеНоооо...
h elto o o o ...
hello o o o ...
X = X + 1; helloooo,..
C o u n t 10
}
M e s s a g e B o x .S h o w ( r e s u l t + "C ount: " + e 2 .c o u n t);
OK

c la ss {
p u b lic i n t ________ = 0;
Дополнительны й
p u b lic s t r i n g ________
в о пр о с!
retu rn " h e llo o o o ..
Как решить задачу, чтобы
} вместо 10 в последней
строке оказалось 24? Для
} этого достаточно заме­
нить всего один оператор.
К аж д ы й ф р а г­
м ент можно
и с п о л ь зо в а ть <4
IS 'теч*' X
н е с ко л ь ко раз! Echo
х х<5
у X > 0 Tester
е2 X > 1 Echo() е2 = е1;
count count(; Echo е2;
ЄІ = ЄІ + 1;
НеІІо() Echo е2 ■ el; x==3
ЄІ = count + 1;
Echo е2 ■ new Echo(); x == 4
el .count = count + 1;
el count = e1 count + 1;

ж®;
ОіюБЄї О на с.
дальше *
работающий класс guys

Помогите парням
Джо и Боб все время одалживают друг другу деньги. Напишем программу отслежи­
G uy
вания истории займов. Для начала нужно понять структуру создаваемого класса.
Name
Cash
Создадим класс би у и добавим в цю рм у два е го экземпляра
Первое поле формы будет называться j ое (для слежения за первым
объектом), а второе bob (для слежения за вторым объектом). GiveCashO
ReceiveCashO
Оператор neWj
создающий экземпляры Os
запускается в м омент
загрузки формы. На
рисунке представлен Итак, наш класс на­
вид кучи после этой зывается Quy (Парень).
операции. Метод GiveCaskQ
’Ьект отвечает за передачу
денег в долг, а м е ­
тод ReceiveCashQ —
за их получение. Поля
Name и Cash содержат
информацию об имени
о Сопоставим каж дом у объекту б и у поля N am e и Cash
Два объекта соответствуют двум парням, у каждого из кото­
и сумме соот вет ­
ственно.
рых есть свое имя и некоторое количество денег в кошельке.

Поле Name содержит .


информацию 00 —р
имени парня, а поле
Cash —- о сумме его
наличности.

Ч5іект&'^ Параметром
метода ReceiveCash()
является количество
получаемых денег.
Поэтому запись
О П а р н и д а ю т деньги и п о л учаю т и х назад
Метод R e c e iv e C a sh () увеличивает количество денег у объ­
joe.ReceiveCash(ZS)
означает, что Джо
получит Я5" долларов.
екта, а метод G iveC ash () уменьшает этот параметр.

форма вызывает метод ReceмeCash().


\
joe.R eceiveC ash(25) ; —I и 'р

^Ъекг Метод возвращает сум м у, которую


объект добавил к полю Cash.

142 глава 3
объекты, по порядку стройся!

Проект «Парни»
Создайте проект Windows Forms Application (ведь нам понадо­
У п і^ а ж н е н и е
бится форма). В окне Solution Explorer создайте класс с именем
G u y . Добавьте в верхнюю часть файла этого класса строчку u s i n g
S y s t e m . W i n d o w s . F o r m s ; , затем введите следующий код:

Поле Name — это строка,


с именем парня (Joe), а поле Cash
целое число, указываюш,ее на
количество наличных денег.
class Guy { Метод diveCasH) имеет
ртіЬІіс string Name; единственный парамет р
public int Cash; am ount, указываюш,ии,
сколько денег следует
отдать. /К
public int GiveCash(int amount) {
if (amount <= Cash && amount :
Оператор if проверяет, хватает ли
Л Cash -= amount;
денег на возврат долга. Если да,
Т ребуем ая сум м а return amount;
Золжнд бы т ь \ else {
б ольш е нуля.
И н аче ден ьги
MessageBox.Show(
б у д у т добавлены "У меня не хватает денег + amount.
в к о ш е л е к , а не Name + " говорит ");
взят ы о т т у д а .
return 0; ® случае нехватки денег появляется
} окно с сообщением, а мет од СЦуеСавНО
возвращает значение о (ноль).
}
М е т о д R e c e iv e C a s h Q т а к ж е
и сп о л ьзует в качест ве
public int ReceiveCash(int amount) { п арам ет ра перем енную
if (amount > 0) { a m o u n t, п р о в е р я е т ее зн а к ,
Cash += amount; и е с л и о н а б о л ь ш е н у л я ,^
д о б а в л я е т к п е р е м е н н о й cash .
return amount;
} else {
MessageBox.Show(amount + " мне не нужно",
Name + " говорит ■ • • н \ f
.
f

return 0;
Если переменная am ount больше
} нуля, мет од ReceiveCash ()
} добавляет ее к переменной
Cash. В противном случае
Следите за т ем , чтобы появляется окно с сообщением
количество открывающихся и возвращается значение О (ноль).
скобок совпадало с количеством
закрывающихся. ИСР поможет вам
в этой задаче.

дальше > 143


джо говорит: «где мои деньги?»

Форма для Взаимодействия с кодом


Теперь нам нужна форма, которая будет работать с экземплярами ■ф-
класса G u y . Она должна содержать метки с именами парней и ко­ |JoCmJ>oU3Iie
личеством денег у каждого их них, а также кнопки, управляющие
процессом взятия и возврата денег.

Н а м понадобятся две кнопки и три м етки


Две верхние метки должны показывать сумму наличности у каждого из парней. К фор­
ме также нужно добавить поле b an k — это еще одна метка. По очереди выделяйте все
метки и редактируйте их свойство «(Name)» в окне Properties. Присвоив метками имена
joesCashLabel и bobsCashLabel вместо имен labell и 1аЬе12, вы сделаете код более читабель­
ным.

Ц? Fun with ioe and Bob Верхней м е т ­


ке присвойте имя
Э т д кнопка joesCashLabel J сред-
Joe has $50 ^ ней — bobsCashLabel,
вызываем, м ем од a нижней —
ReceiveCashQ Bob has $100
объекта Joe, bankCashLabel.
передаем Свойство Text пока
The bank has $100 можно не редакти -
значение 1 0 ровать.
и вычимаем
из поля bank Qve $10 to Receive $5
сум м у, которую Joe from Bob Эта кнопка вызывает
/получает Джо.
мет од QiveCashQ
объекта Bob,
передает значение S
и прибавляет его
О П о л я формы
к полю bank.

Для отслеживания финансового состояния наших героев потребуются два поля. Назовите
их j ое и bob. Затем добавьте поле с именем b an k для расчета, сколько форма должна взять
у объектов, а сколько отдать им. Дважды щелкните на третьей метке и добавьте в появив­
шийся код строки:
n am esp ace Y o u r_P roject_N am e {
p u b lic p a r tia l c la ss Form l : F orm {

Guy joe?
Поля Joe ------^
и Bob объяв- Guy bob ; Значение поля ban k
лены в классе т о возраст ает , т о
in t bank ■ 100; И м еньилает ся в з а ­
Guy. ви си м ост и о т т о го
p u b lic F o rm l0 { ^1<олько д е н е г ф о р м а
In itia liz e C o m p o n e n t(); о т д а л а о б ъ е к т а м Quu
и ск о л ьк о взяла о т них
}

144 глава 3
объекты, по порядку стройся!

О М етод , обновляю щ ий м етки


Д о б а в и м к ф о р м е м е т о д U p d a te F o r m ( ) , ч т о б ы м етк и всегда показы вали актуальное кол и­
ч еств о денег. Убедитесь в наличии модификатора v o id , так как д а н н ы й м е т о д н е д о л ж е н
в о зв р а щ а т ь з н а ч е н и е . Д о б а в ь т е э т и с т р о ч к и п о д п р е д ы д у щ и й код:

М етки U p dateForm О {
ляю т сй при jo esC a sh L a b el .T ex t = jo e .N a m e + им еет $" + jo e .C a s h ; Этот метод
и м е е т $" + b o b . C a s h ;
обновляет м е т ­
поМОЫА,и п о л е й г b o b s C a s h L a b e l . T e x t = b o b . Name +
N a m e и C a sh J - i ки, изменяя их
м е т о д а G u y. ( b a n k C a s h L a b e l . T e x t = "B б а н к е с е й ч а с $" + b a n k ; свойство Text.

Код взаимодействия кнопок с объектами


У бедитесь, ч то кнопка назы вается b u t t o n l , а кнопка справа - b u t t o n 2 . Д важ ды щ елкни­
т е н а к а ж д о й и з к н о п о к , ч т о б ы д о б а в и т ь м е т о д ы b u t t o n l _ C l i c k {) и b u t t o n 2 _ C l i c k ( )
соответственно, и д л я к а ж д о й к н о п к и в в е д и т е код:

p r iv a te v o id b u tto n l_ C lic k (o b je c t sen d er, E ventA rgs e) {

if ( b a n k >= 1 0 ) { ^ ^ 'Мслцщ на кнопке Give ^ г о to Joe,


b a n k -= j o e . R e c e i v e C a s h {10) ; / Ф°рма вызывает метод ReceiveCaskh

} e ls e {
M e s s a g e B o x . S h o w ( "B б а н к е н е т д е н е г . " ) ;

^ Чтобы дать деньги Дж о, в банке должно


} X. быть не меньиле Если их нет,
появляется окно с сообщением.
p riv a te v o i d b u t t o n 2_ C l i c k ( o b j e c t sen d er, E ven tA rgs e) {
b a n k += b o b . G i v e C a s h ( 5 ) ;

U p dateF orm O ; ^ ^ о п к а Я есел ч е f r o m ЪоЬ д о б а в л я е т

I 6 Ът ьш .
Ц 5o6a метод GiveCashQ
возвращает О.

О Начальны й кап и та л Д ж о $ 5 0 , а Боба — $ 1 0 0


А теперь самостоятельно укажите начальное состояние полей Cash и Name для
обоих экземпляров. Код расположите под строкой I n i t i a l i z e C o m p o n e n t ( ) , ведь
процедура должна выполняться при инициализации формы. Завершив работу, убе­
дитесь, что щелчок на левой кнопке забирает $10 из банка и отдает эту сумму Джо,
а вторая кнопка забирает у Боба $5 и возвращает их в банк.

p u b lic Form l О { А с>^ явьт е к о д , со зд а ю щ и й


In itia liz e C o m p o n e n tO ; _________ — ^в а э к з е м п л я р а и з а д а ю -

„ з а д а й т е н а ,а л ь н ь .е з н а ^ е н и ^ и Т Г е Г л /^ Г
}

ажнеше дальше ► 145


объекты, по порядку стройся!

Более простые способы присвоения начальных значений


Практически всегда создание объектов сопровождается присвое­
нием им начальных значений. Объект G u y не исключение —он бес­ Инициализаторы
полезен, если не заданы значения полей N a m e и C a s h . Для решения
этой задачи в C# существует инициализатор объектов. В его основе о^ектов экономят
лежит технология IntelliSense.
ваше время и уве­
Рассмотрим исходный код, присваивающий полям личивают ком­
объекта Joe начальные значения.
joe = new Guy О ; пактность и чита­
joe.Name = "Joe";
joe.Cash = 50; бельность кода.
О Удалите две последние строки и точку с запятой после Guy {) и добавьте справа
фигурную скобку,
joe = new Guy о {
О Нажмите пробел. Появится окно со списком полей, для которых могут быть за­
даны начальные параметры.
joe = new Guy о {
ф Cash int Guy.Cash
0 Name
Нажмите Tab, чтобы добавить поле C ash. Затем присвойте ему значение 50.
joe = new G u y O { Cash = 50

О Введите запятую, и сразу после нажатия пробела появится еще одно поле,
joe = new G u y O { Cash = 50,

ф N am e string Guy.Name

Завершите работу инициализатора. Итак, вы уменьшили свой код на две строчки!


joe = new G u y O { Cash = 50, Name = "Joe" };

Новое объявление выполняет m y ж е ф у н к ­


цию, что и приведенные вначале три
с Т р о ч т к о д і Но оно короче и пройде для
чтения.

дальше > 147


несколько советов

- з д а н и е u H in J J u n iu B H o ц о н я щ н ь іх кЛ ассоБ
G

★ Программа должна решать какую-то задачу.


О бдумайте проблему. Ответьте на вопросы: легко ли ее поделить на несколько ча­
стей, и как бы вы объяснили ее другому человеку?
—у --------- ^
Мне нужно сравнить
несколько маршрутов и
выбрать самый короткий....

★ С какими реальными объектами работает программа?


Программе кормления животных в зоопарке наверняка потребуются клас­
сы для различных видов корма и различных видов животных.

ROAD CLOSED
CHEMIN FERMÉ І
★ Присваивайте классам и методам значимые имена.
Другие пользователи должны понимать назначение классов и методов по виду их
имен.

★ Ищите сходство между классами.


Классы, выполняю щ ие одинаковые функции, имеет смысл объединить. В системе,
производящ ей батончики, может быть несколько турбин, но для закрытия клапана
достаточно одного метода, в котором номер турбины будет использован в качестве
параметра.
ПерекрытаяДорога к
Название О бъ езд
Тупик Название
Длина НазваниеУлицы Длина
ПричинаЗакрытия ПричиныЗакрытия
ПоискОбъездаО
РасчетЗадержкиО ПоискОбъездаО
РасчетЗадержкиО

148 глава 3
объекты, по порядку стройся!

Добавьте кнопки к программе «Веселимся с Джо и Бобом», чтобы заставить парней


к р а ш е н и е передавать друг другу деньги.

П р исво йте экземпляру Bob начальные значения при пом ощ и


ини циал изатора
Вы уже проделывали эту операцию с экземпляром Joe. Потренируйтесь
в работе с инициализатором объектов еще раз.
Если вы поспешили и уже щелкну­
ли Нй кнопке, удалите ее, добавь­
те заново и присвойте новое имя.
Зат ем удалите старый методу
button3_Click() и добавьте новый. \
О Ещ е две кнопки для срормы
Пусть при щелчке на первой кнопке Джо отдает Бобу 10 долларов, а
\
!
при щелчке на второй Боб дает Джо 5 долларов. П еред двойным щелч-
ком на кнопке поменяйте ее имя в окне Properties, используя свойство
«(Name)». Первой кнопке присвойте имя joeGivesToBob, а второй —имя
bobGivesToJoe.

Щ Fun with Joe and Bob

Joe has $50


Bob has $100
Эта кнопка заставляет ТТтє b a * has $100
Ажо отдать й-О долла
ров 5обу, поэтому вос­
пользуйтесь свойством Give 510 to Receive S5
«(N am e)» в окне Properties, Эта кнопка заст авля­
Joe from Bob ет Зоба отдать Джо
чтобы присвоить ей иМЯ
JoeGivesToBob. \ долларов. Присвойте ей
Joe gives S10 Bob gives 55 имя oobC^ivesToJoe.
to Bob to Joe
J

О Заставим кнопки работать


Дважды щелкните на кнопке joeG ivesT oB ob в конструкторе. Форме будет
добавлен метод jo e G iv e sT o B o b _ C lic k (), который запускается при лю­
бом щелчке на кнопке. Пусть этот метод заставляет Джо отдавать 10 дол­
ларов Бобу. Якяждьт щелкните на второй кнопке и заставьте новый метод
Ь o b G iv e sT o Jo e _ C lic k () передать 5 долларов от Боба к Джо. Убедитесь,
что после передачи денег форма обновляется.

дальше > 149


решение упражнения

Вот как стала выглядеть программа после того, как к ней добавили кнопки передачи денег
аж нш е от Боба к Джо и обратно.

у г ш ш г

p u b lic p a r tia l c la s s Form l : F orm {


G uy j o e ;
Это инициализаторы
G uy b o b ; одьектов для двух
i n t bank = 100; экземпляров класса Quy.

p u b lic F o rm l0 {
In itia liz e C o m p o n e n tO ;
b o b « n ew G u yO { C a sh = 1 0 0 , Name * "Bob" } ;
j o e a n ew Q u yO { C a sh = 5 0 , Name = " J o e" } ;
U p dateF orm O ;
}

p u b lic v o i d U pdateForm O { Чтобы заст а­


j o e sC a sh L a b el.T ext = j o e . Name + " и м е е т $" + j o e . C a s h , вить Джо дать
b o b sC a sh L a b el.T ex t = b o b . N a m e + " и м е е т $" + b o b . C a s h , деньги 5обу, мы
b a n k C a sh L a b el. T ex t = "B б а н к е $' + b a n k ; вызываем м е ­
тод GiveCashQ
}
и передаем воз­
вращаемое им
p r iv a te v o id b u tto n l_ C lic k (o b je c t sen d er, E v e n tA r g s e) {
значение методу
i f ( b a n k >= 1 0 ) { ReceiveCashQ.
bank -= j o e .R e c e i v e C a s h (1 0 );
U p dateF orm ( );
} e lse {
M e s sa g e B o x .S h o w (" B банке нет д е н е г ." ) ;
} Результаты
} работы метода
GiveCashQ ис­
p r iv a te v o id b u tto n 2 _ C lick (o b je ct sender, E v e n tA r g s e) {
пользуются
в качестве пара ~
b a n k += b o b . G i v e C a s h ( 5 ) ;
мет ра метода
U p dateF orm O ;
R.eceiveCashQ.
Важно }
помнить,
кто дает . p r iv a t e v o id jo e G iv e s T o B o b C llc k ( o b je c t se n d e r , E v e n tA r g s e ) {
деньги, \ J b o b . R e c e iv e C a s h ( j o e . O iv e C a s h ( 1 0 ) ) ;
а кто их \ U p d a te F o r m ( ) ; ________ _
получает, j }

p r i v a t e v o i d b o b G i v e s T o J o e _ C X ic k ( o b j e c t s e n d e r , E v e n tA r g s e ) {

V j o e .R e c e iv e C a s h ( b o b .G iv e C a s h ( 5 ) ) г
U p d a te F o r m O ;
}
объекты, по порядку стройся!

еШ ение ® бас:с:е^1Не

Требовалось расположить представлен­


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

p u b lic p a r tia l c la ss Form l : Form


{
p r iv a te v o id b u tto n l_ C lic k (o b je c t send er, E v e n tA r g s e)
{ Вот правильный ответ.
S tr in g r esu lt =
А это ответ на
Echo e l = new E c h o O ; дополнительный вопрос!
Echo eZ = new Ecko( ); Еско eZ = е1;
int X = 0;
while ( ^ ^ ^ ) {
r esu lt = r esu lt + e l.H e llo 0 + " \n " ;

ei-.count = ei-.count + Д-;__


if { X == 3 ) {

e 2 . c o u n t = e 2 . c o u n t + 1;

}
if ) {
е 2 .count = е 2 .count + e l.c o u n t;

x = X + 1;

}
MessageBox.Show(result + "Count; " + e2.count)

c la ss Echo {
p u b lic in t count = 0;
p u b lic str in g HelloQ {
retu rn " h e llo o o o ..." ;
}

дальше * 151
4 щ ипь! и ссылки

10:00 утра. ^
Куда подевались наши данные?

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

Tun переменной определяет, какие данные она MO)kenfi сохранять


Количество встроенных типов C# велико, и каждый из них хранит свой собственный вид данных.
С некоторыми из них вы уже познакомились и даже поработали. Пришла пора узнать о неизвестных
доселе типах, которые крайне пригодятся вам в будущем.

Н аиболее используем ы е типы


Вряд ли вас удивит тот факт, что типы i n t , s t r i n g , b o o l и d o u b le являются
самыми распространенными.
★ i n t хранит целые числа от -2 147483 648 до 2147483647;
★ s t r i n g хранит текст произвольной длины (в том числе и пустую строку
★ b o o l хранит логические значения —t r u e или f a l s e ;
★ форма пред­
d o u b le хранит вещественные числа от ±5.0 •10’^'*до ±1.7 -10“ ®до 16 зна­ ставления, при
чащих цифр. Подобный диапазон выглядит странным и сложным, но на которой число
самом деле все очень просто. Словосочетание «значащие цифры» ука­ хранится в виде
зывает на точность числа: и 35048 410 000000, и 1743059, и 14.43857, мантиссы и по­
и 0.00004374155 имеют по семь значащих цифр. Запись 10-’“ означает, казателя степени,
называется числом
что вы можете хранить любое число не больше 10®”*, при условии что с плавающей т оч­
количество значащих цифр не превышает 16. С другой стороны диапа­ кой (запятой).
зона — позволяет хранить числа не меньше 10"*^^...но как неслож­
но догадаться, опять же при условии, что количество значащих цифр не
превышает 16. Часто вы м еняете
(/ т и п переменной
Ц елочисленны е типы
Когда оперативная память компьютера стоила дорого, а процессоры работали Ьыть решена и при
медленно, использование неверного типа данных могло серьезно замедлить помощи «циклыче
ского присваивания»
работу программы. К счастью, времена изменились и теперь для хранения це­ о котором МЫ по
лых чисел в большинстве случаев достаточно типа i n t . Но иногда требуются говорим через пару
дополнительные возможности, поэтому в C# присутствуют такие типы как; страниц.
★ b y te хранит целые числа от Одо 255;
★ s b y te хранит целые числа от -128 до 127; ^
Бук­ ★ s h o r t хранит целые числа от -32 768 до 32 767; Вуква «5» означает
ва « и » «со знаком». То есть
означа­ ★ u s h o r t хранит целые числа от Одо 65,535; число может быть
ет «без отрицательным.
знака». ★ u i n t хранит целые числа от Одо 4 294 967 295;
★ long хранит целые числа в диапазоне от минус до плюс 9 триллионов;
★ u lo n g хранит целые числа от Одо примерно 18 триллионов.

154 глава 4
типы и ссылки

Типы д л я хранени я очень больших и очень маленьких Ч И С б Л


Иногда семи значащих цифр оказывается недостаточно. Бывает так, что 10*® — недостаточно
большое число, а 10"“*^—недостаточно малое. С такими проблемами сталкиваются программы фи­
нансового учета и научных исследований, и для них в С# предназначены дополнительные типы:
★ f l o a t хранит любое число в диапазоне от ±1.5- 10'^'’до±3.4 ■10*®с 7 значащими цифрами;
~^^с'таЫасто* d e c im a l хранит любое число в диапазоне от ±1.0 • 10'^® до ±7.9 • 10^® с 28-29 значащими
встречается цифрами. Свойство Value
6 программах у п « К о н с т й н т й » — это ^ ^ с л о к о - элемента управле­
финансового торое 6t>! вводите в код. В Ьы ния numericUpPown
учета. ЛX---- ' раженим « in t і - 5;» s — это ^принадлежит
константа.
t/ПМЛІЛЛйН данных
Константы тож е им ею т тип decimal.
Числа, используемые в программе на С#, называются константами... и все они
принадлежат какому-то типу. Попробуйте написать код, присваивающий значе­
ние 1 4 .7 переменной типа i n t :
Description
in t m y in t = 1 4 .7 ;
^ 1 Carmot imptkrtty convert type 'double' to ‘inf. An
explicit conversion Bcists (are you missing # cast?)
П ри компиляции вы увидите:
ИСР сообщает, что константа 1 4 . 7 принадлежит типу d o i i b l e . Вставив в конец
букву F ( 1 4 . 7 F ) , вы поменяете тип константы на f l o a t . А в форме 1 4 . 7М оно
будет принадлежать уже типу d e c im a l.
Попытавшись п р и ­
«М » означает «m oney» своить константу
(деньги). Я не шучу! типа float пере­
Ещ е несколько встр оенны х ти по в менной типа double
Для хранения единичных символов, например, Q, 7 или $ используется или decimal, вы
увидите окно с под­
тип c h a r. Константы этого типа всегда заключаются в одиночные кавычки сказкой.
( ' X', ' 3 '). В кавычки можно заключить и евс-последовательность ( ' \ п ' —
это перенос строки, ' \ t ' —знак табуляции). Хотя в коде эти последователь­
ности фигурируют в виде пары символов, программа хранит их в памяти
в виде одного. К
И наконец тип таких данных как o b j e c t . Вы уже получали объекты, созда­
вая экземпляры классов. Любой из них мог быть переменной типа оЬj e c t. "О связи между
О том, как работают объекты и переменные, которые на них ссылаются, мы типами char
и byte вы узнаете
еще поговорим в этой главе. о главе ■?.

W TVPM в Windows 7 у Калькулятора сущ ест вует и режим «П ро­


грам м ист », позволяющий использовать бинарные и деся­
тичные числа одновременно!
Встроенный калькулятор Windows можно использовать для перевода десятичных чисел в двоичные:
перейдите в Инженерный режим, введите число, и установите переключатель в положение Bin. Для
обратного преобразования достаточно вернуть переключатель в положение Dec. Проделайте эту опе­
рацию с пограни чны м и зн ачен иям и цел ы х ти п о в (скажем, с -32 768 и 255). Вы можете объяснить,
почему в C# используются именно такие значения?

дальше у 155
взять деньги на мороженое

Наглядное предстабление переменных Не все переменные попадают


в кучу. Значимые п^ипы хранят
Данные занимают место в памяти. (Помните кучу из преды­ данные в другой части памяти,
дущей главы?) Значит, следует учитывать, сколько простран­ которая называется стеком,
долее подробно мы поговорим
ства требуется под строку или число в программе. Именно о5 эт ом главе 14.
поэтому мы пользуемся переменными. Они позволяют вы­
делить достаточно места для хранения данных.
Представим переменную в виде стакана. В С# используют­
ся разные стаканы для хранения данных разных типов. Чем
больше переменная, тем больший стакан ей требуется.

Tun int
хранения це з ^47.
не больиле 2. 3-^
Tun short хранит целые
числа до 32.767.

чисел Tun byte хро-нит цифры


от О до 7-55.
long int__ short byte
64 32 16 8

Количество битов, выделяемое под


переменную в м омент ее обьявления.

Числа с десятичной точкой хранятся по другому. Для большин­


ства таких чисел подойдет тип f l o a t , занимающий меньше
всего места в памяти. Если вам требуется большая точность,
используйте тип d o u b le . А для финансовых приложений, в ко­
торых хранится информация о курсах валют, используется тип
d e c im a l.

Впрочем, речь не только о цифрах. (Вы же не наливаете горя­ указать.


чий кофе в пластиковый стаканчик, а холодный в бумажный.)
Компилятор C# умеет обрабатывать и не-численные типы дан­
ных. Тип c h a r хранит один символ, а тип s t r i n g позволяет
хранить целый набор символов. При этом под объект s t r i n g
не выделяется предустановленное место в памяти. Он расши­
ряется в зависимости от количества помещаемой в него инфор­
мации. А тип данных b o o l хранит значения true и false, с кото­
string
рыми вы уже сталкивались при работе с оператором i f .
зависит от
размера
строки

156 глава 4
типы и ссылки

10 литров 6 S -литробой банке


Объявив тип переменной, вы фактически объясняете ком­
пилятору, как ее следует воспринимать. Компилятор ви­
дит стаканы, а не то, что в них налито. Поэтому такой код
работать не будет:
in t leagu esU n d erT h eS ea = 2 0 0 0 0;

short sm a llerL ea g u es = lea g u esU n d er T h e S e a ;

Хотя число 20 ООО попадает в диапазон, заданный для типа


данных s h o r t , переменная l e a g u e s U n d e r T h e S e a была
объявлена как i n t , и компилятор не может положить ее
в контейнер s h o r t . Следовательно, вам всегда нужно сле­
дить за совпадением типов данных.

смысл, так как


^збежать с и т и ^
^%'^опы т ает есТ!^‘'^ /сог^й
^/^ержимое
К о м п и л я т о р « в и д и т » , ч т о вы п ы т а е т е .

$ к о гЬ . С о д е р ж и м о е с т а к а н а m t п р и э т о м н е
и м е е т значен и я.

возьми в руку карандаш_ _ _ _ _ _ _ _ _ _


^Возьм1/
Обведите три оператора, которые не будут компилироваться из-за
V несовпадения типов данных или из-за того, что им пытаются при­
своить слишком большое или слишком маленькое значение.

in t hours = 24; str in g ta u n t = "your m oth er" ;

b y te days = 365;

bool isD o n e = yes; lo n g r a d iu s = 3;

sh ort RPM = 33; char in itia l = 'S '

in t b a la n ce = 345667 - 567; str in g m on th s = "12";

дальше ► 157
приведения

Приведение типов

Посмотрим, что произойдет при попытке назначить


значение типа d e c im a l переменной типа i n t . Vу п |^ а ж н ^е н и е
Создайте новый проект и добавьте кнопку. Для метода
C l i c k О этой кнопки напишите:
d e c im a l m yD ecim alV alu e = 10;
i n t m y ln tV a lu e = m y D ecim a lV a lu e;

M e s sa g e B o x .S h o w (" T h e m y ln t V a lu e is " + m y ln tV a lu e);

© Попытавшись запустить программу, вы получите сообщение об ошибке:

' Q 1 Effor |; ^ ОWaFnings v [h ^ О M essages


Description

О 1 C annot tmpKcttly convert type 'd e d m a f to ’in f. An ecpttcrt conversion ecists (are you nfiissing a cast?) ИСР предполагает,
что вы забыли осуще­
ст вит ь приведение
о Устраните ошибку, преобразовав тип d e c im a l в i n t . Внесите во вто­
рую строку следующие изменения:
типов (casting).

i n t m y ln tV a lu e = (in t) m y D ecim a lV a lu e;
Этот оператор делает
приведение типа decimal
Ч то )ке произошло? к т ипу int. Вернитесь в начало
'предыдущей главы
Компилятор не позволяет присваивать значения несовпадающих ти­ « посмот рите, как
пов, даже если переменная попадает в правильный диапазон. Приведе­ ^ приведение типов
ние типа —это объяснение компилятору, что вы знаете о несовпаденйи использовалось для
і^ередачи значения
типов, но в данном конкретном случае осознанно осуществляете опера­
^J^'^encUpDown ф ор­
цию присваивания. м е Talker Tester

Вот операторы, которые не будут компилироваться из-за несо­


аж нш е впадения типов данных или из-за того, что им пытаются присво­
ить слишком большое или слишком маленькое значение.
Слишком большое
sh ort у = 78000;
число. Тип short
хранит значения от
-ЗЯ,767 до 32..,762.
С b y te days = 365;

bool isD o n e = yes


Переменной типа bool переменные т ш а К
можно присвоить только хранят числа do % s f
значения true или false.

158 глава 4
типы и ссылки

Автоматическая коррекция слишком


больших значений
Вы уже видели, что тип d e c im a l может быть приведен
«о Г э ч З Г *
к типу i n t . Получается, любое число может быть приве­
дено к любому типу. Но это не означает сохранение зна­
чения. Приведем переменную типа i n t со значением 365
к типу b y te . Число 365 выходит за границы диапазона
этого типа. Но вместо сообщения об ошибке произойдет
циклическое присваивание: например, 256 после при­
ведения к типу b y te превратится в О, 257 —в 1, а 365 — возьми в руку карандаш
в 109. Как только вы дойдете до 255, произойдет переход
к нулевому значению. О п ер ац и я при в ед ения раб о тает
не со всем и ти п ам и . Создайте новый проект,
добавьте кнопку, дважды щелкните на ней
и введите следующие строки. Попытайтесь
построить программу. Зачеркните строки с
О О Еще в главе 2 я начал ошибками. Это поможет понять, для каких
комбинировать строки с типов приведение допустимо, а для каких нет.
цифрами в окнах диалога!
in t m y in t = 10;
Получается, я все это время
преобразовывал типы данных? b y t e m yB yte = (b y te )m y in t;

d o u b l e m y D ou b le = (d o u b le)m y B y te;

b o o l m yBool = (b o o l)m y D o u b le;


Да! Это д елал за ва с оператор + . s t r i n g m y S tr in g = " fa ls e " ;

ч Вы пользовались оператором +, который


автоматически преобразовывал дан­
ные. Когда вы добавляли число и логиче­
ское значение к строке, указанное вами
myBool =

m y S trin g =
(b o o l)m y S trin g ;

(str in g )m y in t;

значение автоматически преобразовы­ m y S trin g = m y in t. T o S t r in g ();


валось к типу string. Операторы + (или *, myBool = (b o o l)m y B y te;
/ или -), примененные к значениям раз­
личных типов, автоматически преобра­ m yB yte = (b y te)m y B o o l;
зовывают меньший тип в больший. Вот
s h o r t m yShort = (sh o rt)m y in t;
пример:
in t m yInt = 36, c h a r m yChar = 'x ';
После числа, кот о­■ —' d o u b l e m y F l o a t = 1 6 . 4D;
m y S trin g = (strin g )m y C h a r;
рое присваивается
m y F lo a t = m y in t + m y F lo a t ;
переменной типа
l o n g m yLong = (lo n g )m y in t;
double, нужно до­
бавлять р, чтобы Диапазон значений типа i n t больше диа­
d e c im a l m yD ecim al = (d e c im a l)m y L o n g ;
указат ь ко м ­ пазона значений типа f l o a t , оператор +
пилят ору на его преобразует переменную m y in t к типу m y S tr in g = m y S tr in g + m yin t + m yB yte
!лринадлежность f l o a t и только потом прибавляет ее к пе­ + m y D o u b le + m yChar;
к т ипу float.
ременной m yF loat.

дальше ► 159
настоящее преобразование

иногда приведение типов происходит автоматически


Есть два случая, когда вам не требуется делать приведе­
ние типов. Автоматически эта процедура выполняется,
во-первых, при проведении арифметических опера­
ций:

П арам ет р т ипа
lo n g 1 = 139401930;
sh o rt вы чит ает ся
из п а р а м е т р а т и п а
sh ort s = 516;
lo n g , а о п е р а т о р =
п р ео б р а зует
d o u b le d = 1 ;
р езул ьт ат к т ипу нение--------- ----------
d = d / 1 2 3 .4 5 6 ;
d o u b le .
)'^ешенке
M e s s a g e B o x . S h o w ( "О твет " d) ; И так, вы у б е д и л и с ь , что п р и в е д е н и е в о з­
м о ж н о д а л е к о не д л я всех ти п о в . Зачер­
кнутые строки не позволяют осуществить
В л а го д а р я о п е р а т о р у ^ построение программы.
п р о и сх о д и т п реоб разован и е
т и п а d e c im a l к т и п у s tr in g . in t m y in t = 10;

b y t e m yB yte = (b y te )m y in t;
Во-вторых, автоматическое преобразование происхо­
d o u b l e m yD ou ble = (d o u b le)m y B y te;
дит при объединении строк оператором Все числа
при этом преобразуются к типу string. Рассмотрим при­ bqrri—и у В в е 1 ■—— —
мер, в котором первые две строки кода написаны пра­
вильно, третья не может быть скомпилирована. str in g m yS trin g = " f a l s e " ;

lo n g X = 139401930; -royBool—=— (Jaooif) my Ot r i n g - ,-^

M e s s a g e B o x .S h o w (" О т в ет " + х ) ;
mygtrrreg--~~4-&fe*4:ag-)-my»m‘fe-;—^
m yS trin g = m y in t.T o S tr in g ();
M e s s a g e B o x .S h o w ( х ) ;
- « ¥ E ucl1—^=— (-b e o l ) m y B y t «-,-
Компилятор выдает сообщение об ошибке в связи с не­
правильным аргументом (аргументом в C# называется —(fa^'tTc:') myOoa lf ----
значение, передаваемое методу в качестве параметра). s h o r t m yShort = (sh o rt)m y in t;
Параметр метода M e s s a g e B o x . S h o w O должен при­
надлежать типу s t r i n g , код же передает переменную c h a r myChar = ' x ' ;
типа l o n g . Впрочем, вы легко можете осуществить jny S t r ir a g —^— (-at r i n g ) m y e h a g ;
это преобразование при помощи метода T o S t r i n g ( ) .
Этим методом обладают все объекты. (И все создан­ l o n g m yLong = (lo n g )m y in t;
ные вами классы имеют метод T o S t r i n g ( ) , возвраща­
d e c im a l m yD ecim al = (d e c im a l)m y L o n g ;
ющий имя класса.) Именно с его помощью можно пре­
образовать X в параметр метода M e s s a g e B o x . S h o w (): m y S t r i n g = m y S t r i n g + m y in t + m yB yte
+ m y D o u b l e + m y C h a r;
M essageB ox. S h ow (x. T o S tr in g ( ) ) ;

160 глава 4
типы и ссылки

Аргументы метода дол)кньі б ы ть совместимы с типами параметров


Попытайтесь вызвать метод Me s sa g e B o x . Show ( 12 З ), то есть передать ^ - Параметр ~ это то,
чмо вы определяете
методу M essageB ox.Show () константу (123) вместо строки. ИСР не внутри метода, а а р ­
позволит построить программу. Появится сообщение об ошибке: «Аргу­ гумент — что в него
мент ‘1’: преобразование из типа i n t в тип s t r i n g невозможно». Ино­ предает ся. Метод
гда преобразование происходит автоматически, например, если ожида­ с парамет ром типа int
лось значение типа i n t , а вы передали методу значение типа short, но может принять а ргу­
м ент типа byte.
в случае с переменными типа i n t и s t r i n g это невозможно.
Не только метод M essageB ox.Show O , все методы, даже написанные
вами, будут показывать ошибку компиляции, если передать им пара­ Ошибка <<неверный
метр неправильного типа. Попробуйте использовать на практике этот
совершенно правильный метод: ар1умент>> означает,
p u b l i c i n t MyMethod (b o o l yesNo) {
что вы попытались
if (yesNo) {
вызвать метод с пе­
r e t u r n 45;
^йї?еменная yesNo
ременными, тин ко­
} e ls e {
r e t u r n 61; торых не совпадает
} с его параметрами.
}

Все работает, пока вы передаете методу то, что он ожидает получить (логиче­
скую переменную), вызов MyMethod ( tr u e ) или MyMethod ( f a l s e ) позволяет
легко скомпилировать код. ^ ^
Переменной, парам е-
Но что получится, если передать методу число или строку? Вы получите <тру или полю Можно
уже знакомое сообщение об ошибке. Попытайтесь передать параметр типа Р\р01АЗ —
вольное значение при
B o o lean , но в качестве возвращаемого значения укажите строку или передай­
помощи типа object.
те результат методу M essageB ox. Show (). Код перестанет работать, ведь ме­
тод возвращает значение типа i n t , а не lo n g или s t r i n g , которое требуется
методу M essageB ox. Show().

ш «ижно л и м т ь в явном биде if (yesNo == tru e), т ак кяк


Не нужно писат о о uomuHHOcmf условия. Для
оператор всегда про Р итользчйте оператор !

условия.

дальше > 161


таблица зарезервирована Вы можете использовать для имен переменных даже
, зарезервированные слова. Достаточно поставить
у в начале знак
В С # существует около 77 зарезервированны х слов. Их нельзя использовать в
качестве имен переменных. К концу данной книги вы должны познакомиться с ними
нение всеми, а пока посмотрите на список слов, с которыми вы уже сталкивались. Напи­
шите, зачем они нужны.

na m e s p a c e

£ог

class

p u bl ic

else

while

using

if

пеуг

О ш Б е г п ы н а с. 9
162 глава 4
типы и ссылки

Создадим калькулятор расходов для деловой поездки. Вы будете вводить данные с одометра
п^ражнение в начале и конце путешествия, а счетчик вычислять, какое расстояние было пройдено и какую
сумму денег вам вернут в бухгалтерии, при условии, что за каждую пройденную милю полага­
ется $.39.

О Новы й проект W indow s.


Вам понадобится вот такая форма:
Избавьтесь am
кнопок управления
Mileage Cakulator размером окна.
Д ая этой
ааШпд Mileage
мет ки ис~ В
пользуйте Endng Wteage
‘полужирный
ш риф т и
кегль 1 2 p t Anourt Owed la b e H
Calculate

Завершив создание формы, дважды щелкните на кнопке и добавьте код.

О П ер ем енны е, которые потребую тся для калькулятора.


Поместите переменные в строчки, объявляющие класс, в верхней части кода
F o rm l. Вам потребуются две целочисленные переменные для начальных и
конечных показаний одометра. Присвойте им имена sta r tin g M ile a g e и
e n d i n g M i l e a g e . Затем вам потребуются три нецелых числа. Выберите для
них тип d o u b l e и имена m i l e s T r a v e l e d (Пройдено миль), r e i m b u r s e R a t e
(К оэфф ициент возмещения) и a m o u n t O w e d (Должны денег). Переменной
r e i m b u r s e R a t e присвойте значение .39.

Чтобы заставить калькулятор работать.


Добавьте код для метода b u t t o n l _ C l i c k ( ) :
★ Убедитесь, что значение поля StartingMileage меньше значения поля
EndingMileage. В противном случае должно выводится окно с текстом «На­
чальный пробег не может превышать конечный». Присвойте этому окну имя
«Cannot Calculate» (Невозможно рассчитать).
★ Вычтите начальный пробег из конечного и умножьте полученный результат
на тариф;
m ile sT r a v e le d = e n d in g M ile a g e -= sta r tin g M ile a g e ;
am oun tO w ed = m ile sT r a v e le d *= r e im b u r se R a te ;
la b e l4 .T e x t = "$" + am oun tO w ed ;

З ап уск прогроАлмы.
Убедитесь в вводе правильных значений. Укажите начальный пробег больше конеч­
ного и убедитесь в появлении окна с сообщением.

дальше > 163


что-то пошло не так...

Во т как выглядит код для первой части упражнения по расчету


нгнш компенсации.
ешение

p u b lic p a r tia l c la s s Form l : Form

{ ■^ак как в данном


in t S ta r tin g M ile a g e ; случае число может
превысить 999 999
in t e n d in g M ile a g e ; типы short или byte не
подходят.
d o u b le m ile sT r a v e le d ;

d o u b le r e im b u r se R a te = .3 9 ;

d o u b le am oun tO w ed ;

p u b lic F o rm l0 {

In itia liz e C o m p o n e n t();

} П ом ни те, « ,ц ц я
, э л е м е н т а управления
p r iv a te v o id b u tto n l_ C lic k (o b je c t sender, E ven tA rgs e) { ,,iflA ericU p'P ovJn о а м
н у ж н о п о т н я т ^ > у^ ^ ^
S ta r tin g M ile a g e = (in t) n u m e r ic U p D o w n l.V a lu e ;
d L l m a l на m t.
e n d in g M ile a g e = (in t)n u m e r ic U p D o w n 2 .V a lu e ; ^

if (sta r tin g M ile a g e <= e n d in g M ile a g e ){


Здесь рассчиты­
m ile sT r a v e le d = e n d in g M ile a g e -= sta r tin g M ile a g e ; ) ваете количество
am ou n tO w ed = m ile sT r a v e le d *= reim b u rseR a te ;
пройденных миль,
которое зат ем
la b e l4 .T e x t = "$" + am oun tO w ed ; j* умножается на
тариф возмеще­
} e ls e { ния расходов.
M essageB ox. Show (
"Начальный пробег не может превьшать конечный",
"Cannot C a lc u la te M ile a g e " ); Здесь использует ­
ся альт ернат ив-
} ^ ный способ вызова
\ MemodaMessageBox.
^ SkowQ. Первый пара­
м ет р — это от о­
бражаемое сообщение,
а второй — заголовок.
Кнопка, каж ется, работает, но есть одна
проблем а. Вы м ожете указать ее?

164 глава 4
типы и ссылки

Ещ е одна кнопка
Попытаемся понять, почему не работает форма, добавив еще одну кноп­
ку, которая будет показывать значение поля m ile s T r a v e le d . (Это можно
сделать при помощи отладчика!)

Если сначала щелкнуть


Satffig Weage 1Ш Э на кнопке Calculate, а потол/\
на этой кнопке, должно п о ­
Bid^g Meage 12354 явиться окно диалога с иказа-
нием пробега.
AmoirrtOwed $532.35 •ВЧТЯГЯЯТТГЯЯТТГЯЧИТЯТКЯРм^!
Calcdate

Закончив конструирование формы, дважды щелкните на кнопке Display


Miles, чтобы добавить код.

О П онадобится всего одна строка


Нам нужно окно, в котором будет отображаться значение переменной
m ile s T r a v e le d , не так ли? Для этого достаточно одной строки:
p r iv a te v o id b u tto n 2 _ C lic k (o b je c t send er, E ven tA rgs e) {

M e s s a g e B o x .S h o w (m ile s T r a v e le d + " m ile s" , " M ile s T r a v eled " );

З ап уск програ/имы
Введите какие-нибудь значения и посмотрите, что
получится. После ввода начального и конечного про­
бега щелкните на кнопке Calculate. После этого щел­
чок на кнопке Display Miles покажет значение поля
m ile sT r a v e le d .

Вот только странно...


П ри любых введенных значениях пробег совпадает с суммой возмещения. Почему?

дальше > 165


операторы наготове

Комбинация с оператором =
Обратите внимание на оператор, который использовался для вычитания на­
чального пробега из конечного (-=). Проблема в том, что он не только вычита­
ет, но и присваивает значение переменной. То же самое происходит в строке,
где мы умножаем пройденные мили на тариф возмещения. Поэтому нужно
заменить операторы -= и *= на - и *:

p r iv a te v o id b u tto n l_ C lic k (o b je c t sender, E ven tA rgs e)


»созыва-
{ соси^авные
S ta r tin g M ile a g e = (in t) n u m e r ic U p D o w n l.V a lu e ; •^Р<^сваиёа~
e n d in g M ile a g e = (i n t ) n u m ericU p D o w n 2 . V a l u e ; operators).
if (sta r tin g M ile a g e <= e n d in g M ile a g e ){

m ile sT r a v e le d = e n d in g M ile a g e ^ ^ ^ ^ ta r tin g M ile a g e ;

am oun tO w ed = m ile sT r a v e le d (^ ^ )r e im b u r se R a te ;

la b e l4 .Text = "$" + am oun tO w ed

} e ls e {

M e s s a g e B o x .S h o w ("Н ачал ьны й п р о б е г fce мож ет превы ш ать конечны й"


"Cannot C a lc u la te ^ le a g e " );

При такой записи код не


будет менять? зидчение
переменных endingMileage milesTraveled = endingMileage - startingMileage
и milesTraveled.
amotmtOwed = milesTraveled * reimburseRate;

П о м о гл и л и нам значимы е и м ен а переменны х? Конечно! Посмо­


трим на функцию каждой переменной. По названию m i l e s T r a v e l e d
(Пройденные мили)вы понимаете, что эту переменную форма отобра­
жает неправильно и догадываетесь, как можно исправить ситуацию.
Вам было бы намного сложнее локализовать проблему, если бы код вы­
глядел вот так:
тТ = еМ - = sM ; таки АЛ ,
аО = т Т *= r R ; > менных невоТлТ‘^ ^
S^ бы полн^ он и

166 глава 4
типы и ссылки

Объекты то)ке используют переменные


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

Работа с типом int Работа с объектом

(l) Пишем оператор объявления типа. Пишем оператор объявления типа.

int myint; Dog spot; объяблети


переменной название
класса используется
в качестве типа.
(8) Присваиваем новой переменной зна­ О Присваиваем новой переменной значение:
чение.
spot = new Dog();
myint = 3761;

(З) Используем переменную в коде. О Проверяем одно из полей объекта.

while (i < myint) { while (spot.IsHappy) {


___/ Получается, что нет разницы \
^ с чем работать, с объектом или с числом. )
В любом случае я работаю с переменной. )
О

Д а, об ъ екты — это всего л и ш ь ещ е один


тип перем енны х.
Если программе нужны целые большие числа,
используйте тип lo n g . Для целых малых чи­
сел используйте тип s h o r t . Если вам нужны
значения Д а/Н ет, используйте тип b o o le a n .
А если вам нужно нечто лающее, используйте
тип Dog. Во всех случаях вы работаете с пере­
менными.

дальше ► 167
получи ссылку

Переменные ссылочного типа


Э т о н а э ь 1 ва е т ся
Для создания нового объекта вы пишете n e w G u y ( ). Но этого недоста­ созданием экземпляра
точно; в куче появится объект G u y, но у вас не будет к нему доступа. Вам объекта. \
требуется ссылка на объект. Здесь на помош;ь приходят п е р е м е н н ы е с с ы ­
л о ч н о г о т и п а —это переменные типа G u y , имеюш;ие имя, например, j o e .
В итоге получается, что j o e —это ссылка на только что созданный объект
G uy. Именно она используется для доступа к объекту.

Все переменные типа object являются ссылочными. Давайте рассмотрим


пример:

Это куча до
запуска кода. Там
ничего нет.

p u b lic p a r t i a l c la s s F o rm l Form
{
Guy joe;

p u b lic F o rm l0
Это переменная { Создание ссылки подобно
joe, ссылающаяся I n i t i a l i z e C o m p o n e n t () наклеивании) стикера, вы
на объект йму< помечаете объект, чтобы
joe = new Guy(); получит ь возможность
ссылаться на него в даль­
нейшем.
Это ссылочная ^ объект,
переменная... на который
она ссылается.

Вид кучи после запу таинственный


ска кода. Теперь т ам к объ­
находится объект ект у Quy - аерез
с переменной Joe. хо ^^^ременную Joe
торая на него ссыла­
ется.

168 глава 4
типы и ссылки

Ссылки подобны маркерам


Подозреваем, что на вашей кухне есть отдельные емкости для сахара
и соли. Если поменять местами наклейки на них, еда будет несъедобной,
ведь содержимое емкостей при этом местами не поменялось. Аналогично
действуют ссылки. Ярлыки можно поменять местами и заставить указывать Для работы с хра­
на разные вещи, но какие именно данные и методы будут доступны, опре­
деляет только сам объект, а не ссылка на него. нящимися в памяти
Метод b u tto n l Clirîf Ar,
мы F orm l содеюжи^ объектами ис­
Это объект типа
^иу. Он ОДИН, но на пользуются ссылки,
него МНОГО ссылок
которые являются
перемеппыми. Тип
этих переменных
определяется клас­
сом объекта, на ко­
торый они ссыла­
ются.

Переменная ^т о ссылочные
«папа» является ’л еременные,
ссылкой на экзем ­ указывающие на
пляр класса Quy. ОДИН И ТО Т ЖЕ
ооьект. Различные методы м о ­
гут использовать эк-
Обращение к объекту никогда не проиходит напрямую. К примеру, не­
ссь/лоч-
возможно записать G u y . G i v e C a s h {), если G u y принадлежит типу object. НЫМ п е р е м е н н ы м р а ­
Компилятор не понимает, куда именно вы обращаетесь, так как в куче мо­ зум н о п р и сво и т ь разн ы е
жет храниться несколько экемпляров G u y. Вам нужна ссылочная перемен­ в зависимости от
ная, например, j o e , которой будет присвоен конкретный экземпляр G u y контекста.
j ое - new G u y ().

Теперь можно вызывать методы j о е . G i v e C a s h ( ), ведь компилятор «зна­


ет», к какому экземпляру обратиться. Как показано на рисунке, возможен
набор ссылок на один экземпляр. Можно написать G u y d a d = j о е и вызвать
метод d a d . G i v e C a s h о (папа.ДайДенег()). Именно этим сын Джо зани­
мается каждый день!

дальше ► 169
вот водитель мусоровоза

При отсутстви и ссылок объект


Объект остается
превращается 6 мусор
Если все ссылки на объект исчезают, программа теряет к нему
в куче, пока на него
доступ. Теперь объект предназначен для сборки мусора
(garbage collection). C# избавляется ото всех объектов, на ко­
есть хотя бы одна
торые нет ссылок, освобождая место в памяти.
ссылка. Как только
^ Вот код создания объекта.
последняя ссылка
G uy j о е = n e w G u y () исчезает, объект
{ Name = " J o e " , C a s h = 50
удаляется.

Оператор new соз­


дает новый объект,
a ссылочная пере­
менная Joe указывает
на него.

О Бьхл создан второй объект.


G uybob = n e w G u y O
{ Name = "B ob", C a s h = 7 5 } ;

о П у сть ссы лка на первый экзем пляр начнет Ссылок Нй пер-


указывать на второй. вый экземпляр
не осталось...
j ое = bob;

■■■поэтому
Объект
удаляется!

170 глава 4
типы и ссылки

Побочные эффекты мно)кественных ссылок


Обращаться с ссылочными переменными нужно аккуратно. В боль­
шинстве случаев кажется, что вы просто перенаправляете ссылку на
другой объект. Но при этом можно нечаянно удалить все ссылки на
другой объект. И далеко не всегда это будет тот результат, который
вам нужен. Рассмотрим пример:

Dog rover = new D og();

r o v e r .B reed = "G reyhound";

О бъ ектов:

© Dog fid o = new DogO ;


fid o .B r e e d = " B e a g le" ;
Dog spot = rover;

О бъ ектов: ^ Fido — это еще один


объект Dog. При эт ом
С сы лок: 5 Spot — это всего лииль
дополнительная ссылка
на первый объект.

Dog lu c k y = new D og();

lu c k y .B r e e d = "D achshund";
Бах!
fid o = rover;

/ Л \
Lucky — это т рет ий
объект. A Fido теперь
ссылается на Object *%.
На object не
остается ссылок. Он
удаляется.
дальше ► 171
так много меток

їозьми в руку карандаш Теперь ваша очередь. Вот длинный код, разбитый на блоки.
Укажите, сколько объектов и сколько ссылок на них имеется на
каждой стадии. Справа нарисуйте объекты в куче и их метки.

Dog rover = new D og();


r o v e r .B reed = "G reyhound";
Dog r in T in T in = new D og();
Dog f id o = new D og();
Dog q u e n t in = fid o ;

О бъ ектов :.

Ссы лок:

© Dog sp ot
s p o t .B reed
= new
=
D o g {);
"D achshund";
sp ot = rover;

О бъ ектов :______

С сы лок:_____

О Dog lu c k y
lu c k y .B r e e d
= new
=
D o g {);
" B e a g le" ;
Dog C h a rlie = fid o ;
fid o = rover;

О бъ ектов :______

С сы лок:_____

^ r in T in T in = lu c k y ;
Dog la v e r n e = new DogO ;
la v e r n e .B reed = "pug";

О бъ ектов :______

Ссы лок:_____

О C h a r lie
lu ck y =
= la v e r n e ;
r in T in T in ;

О бъ ектов :______

С сы лок:_____

172 глава 4
типы и ссылки

Напишите программу для класса e le p h a n t (слон). Получите два экземпляра


e le p h a n t и поменяйте указывающие на них ссылки таким образом, чтобы
ни один из экземпляров не был уничтожен.
ажнение
Н ачните с проекта W indows Application.
Форма должна выглядеть так; А т г р а м м а для

S S e .t e ,- " -
с E le p h a n t
Name
т акое окно.
EarSize

WhoAmIO

убеди т есь, чт о в т екст е


содерж ит ся и н ф орм ац и я
о р а зм ер е уха, а ст роке
за го л о вк а ф и гу р и р у е т
и м я слона.

Класс Elephant
Согласно диаграмме классов E le p h a n t вам потребуется поле типа i n t с названием E a r S iz e
и поле типа S t r i n g с названием Name. (Убедитесь в наличии модификатора public.) Добавьте
метод WhoAmI (), вызывающий окно с информацией о размере уха и имени слона.

о Еще два экзем пляра Elephant и ссы лки на н и х


Добавьте к классу Form l два поля E le p h a n t (сразу под объявлением класса) с именами L lo y d
и L u c in d a. Присвойте им следующие начальные значения;
l u c i n d a = n e w E l e p h a n t О { Name = " L u c i n d a " , E a r S i z e = 3 3 };
l l o y d = new E le p h a n t 0 { Name = " L l o y d " , E a r S i z e = 4 0 } ;

Кнопки Lloyd и Lucinda


Кнопка Lloyd должна вызывать метод 1 l o y d . WhoAmI , a кнопка Lucinda —метод l u c i n d a .
WhoAmI{).
Кнопка переклю чения
Это самая слож ная часть. Кнопка Swap должна поменять местами две ссылки. То есть щел­
чок на ней заставляет переменные L lo y d и L u c in d a ссылаться на другие объекты и вызва-
ет окно с сообщением «Objects swapped» (Замена объектов). После щелчка на кнопке Swap
щелчок на кнопке Lloyd должен вызывать окно Lucinda и наоборот. Повторный щелчок на
кнопке Swap должен возвращать все обратно.

Как только на о б ъ ект не остается ни одной ссы лки, он удаляется. Ч то ж е д ел ать ?


П редставьте, что вы реш и ли пер ел и ть пиво в стакан, которы й в д анны й м ом ент
напол нен водой. Чтобы сд ел ать это вам потребуется ещ е один, пустой стакан...
Возьми 8 руку карандаш Вот как выглядит куча с объектами и ссылками на них.

“^ешение
Dog rover = new D og();
r o v e r .B reed = "G reyhound";
Dog r in T in T in = new D og();
Dog f id o = new D og(); % dof
Dog q u e n tin = fid o ;
(^здан новый объект
^од со ссылкой Spot. В
результ ат е операции
Spot = Rover объект
исчезает.

y/
© Dog sp ot
s p o t .B reed
= new
=
D og();
"D achshund";
^

spot = rover;

Создан новый объект


Dog, но после Fido=Rover
^ предыдущий объект на
/ который ссылался Fido
исчезает
© Dog lu c k y
lu c k y .B r e e d
= new
=
D og();
" B e a g le" ;
Dog C h a rlie = fid o ; . ,,
^ ^ Charlie, как и Fido, стал
fld o = rover; указывать на object
* 3 . Зат ем Fido начал
О бъ ектов: 4 ссылаться на object ^й-.
Исчезла
Ссы лок: 7 последняя
ссылка на ^
объект
r in T in T in = lu c k y ;
Dog
Dog la v er n e = new D o g ()
la v e r n e .B reed = "pug";

О б ъ екто в :. 4
Ссылка Rin Tin Tin
Ссы лок: ^ т е п ^ ь указывает
на объект Lucky,
поэт ому предыдущий
C h a rlie = la v e r n e ; объект был удален.
lu c k y = r in T in T in ;

О бъ ектов: 4
\
Ссы лок: 8 Происходит перенаправление
ссылок, но новые объекты не соз­
даются. Последний оператор не
делает ничего, так как обе ссылки
174 глава 4 и т ак указывали на один и т от
же объект.
типы и ссылки

Посмотрим, как же поменять между собой ссылки на два экземпляра,


пражнение чтобы ни один из них при этом не оказался удаленным.
решение
Э т о определение
к л а с са B ie p h a n t
u s in g S y stem .W in d o w s.F o r m s;
He за б уд ьт е _
c la ss E lep h a n t { строчку
System-Wtn-ftOV/s-
p u b lic i n t E a rS ize; pormSi»>
p u b lic s t r i n g N am e; ие о п е р а т о р
M essa g eB o x не oy
p u b l i c v o i d W hoAmI0 { д е т p a S o m a m t? -
M essa g eB o x .S h o w (" M y e a r s are + E a rS ize + " in ch es ta ll.'
Name + " s a y s . . . " ) ;

p u b lic p a r tia l c la ss Form l ; F orm {

E lep h a n t lu c in d a ;
E lep h a n t llo y d ;

p u b lic F o rm l0

In itia liz e C o m p o n e n tO ;
Это код класса l u c i n d a = n e w E l e p h a n t ()
F orm l из файла { Name = " L u c i n d a " , E a r S i z e = 3 3 } ;
Formi.cs. l l o y d = new E le p h a n t 0
{ Name = " L l o y d " , E a r S i z e = 4 0 } ;
}
p r iv a te v o id b u tto n l_ C lic k (o b je c t sen d er, E ven tA rgs e) {
С с ы л к а H o ld e r llo y d .W h o A m I( ) ;
н у ж н а для т о го }
ц т о б ы о б ш к т L io y d p r iv a te v o id b u tto n 2 _ C lick (o b je ct sen d er, E ven tA rgs e) {
не и сч ез, п о сл е т о го lu c in d a .W h o A m I( ) ;
как ссы лка б уд ет
п е р е н а п р а в л е н а на
}
объект Lucinda. p riv a te v o id b u tto n 3 _ C lick (o b je ct sen d er, E ven tA rgs e) {
- E lep h a n t h o ld e r ; О п е р а т о р n e w не и с п о л ь з у е т с я ,
S S r= ^ u c? n d ;; ^ ^ т а к к а к н а м не н у ж е н е щ е оЗын
lu c in d a = h o ld e r ; э к з е м п л я р E le p h a n t .
M e s s a g e B o x . S h o w ( "Obj e c t s s w a p p e d " ) ;
}

Типы данных string


и array от личаю т ­
ся от всех остальных
от сут ст вием фикси­
рованной длины.
Как вы считаете, почему к классу Elephant не был добавлен метод Swap()?
держи ссылку

Дбе ссылки это Д В А способа редактировать данные объекта


Наличие множественных ссылок на объект создает
опасность непреднамеренного редактирования. Дру­
V ^
гими словами, одна ссылка может енести изменения
в объект, в то время как другая рассчитана на исполь­
зование старой версии этого объекта. Посмотрите
сами:

О Добавим форме еще одну кнопку.

© Добавим к кнопке код. А теперь подумайте, что


произойдет после щелчка на этой кнопке?
После запуска кода
p riv a te v o id b u tto n 4 _ C lick (o b je ct sen d er, E v e n tA r g s e) 1^еаеменные lloyd
{ и lucinda будут
Этот опера­ llo y d = lu c in d a ; ■■— ссылаться на ОЛИН
тор прцсбаива- . llo y d .E a r S iz e = 4321; объект Elephant.
ет переменной-^ l l o y d . W h o A m I {) И е т о З WboAmiO
EarSize значение вы зы вает е^
43Д 1 т ому объекта
объекту, на ко­
торый покажет
ссылка lloyd.
С Но lloyd указывает
же, куда и lucinda.

Щ елкните на кнопке, чтобы проверить свои догадки. Смотрите, это окно ^1ер)г\0!Г^
Lucinda. При том что вы вызывали метод WhoAmI () для Ллойда.

Lucinda says...
Но это значение
Окно Аизсинды... <^е.ременной
EarSize было
определено для
Ллойда. Что
'происходит'?

Данные при эт ом
не п ереп и сы вали сь,
изменились толч^ко
ссылки.

176 глава 4
типы и ссылки

Особый случай: массиВы


Для слежения за набором данных одного типа, например, спи­
ска высот или группы собак используются м а с с и в ы (a r r a y ). Этот
термин обозначает г р у п п у п е р е м е н н ы х , которая обрабатыва­
ется как единый объект. Вы получаете возможность хранить
и редактировать большие наборы данных. Массивы объявляют­
ся аналогично другим переменным. Нужно указать имя массива значений:
и его тип: Ьоо1[]
new
Для об-ьявления мяссибя
нужно указат ь его т ип,
поставив следом ква bool [] туАггау;
дратные скобки. состоит из
1 5 элементов.
туАггау = new bool
— -
Новый массив С03-,
дается командой туАггау[4] = true
new, как и любой
другой объект.
Нумерация элементов массива нйим
Ка)кдЬ1й элемент waccuBa — это всего лишь переменная нается с О. Эта строка присваивает
пят ому элементу массива значение
Прежде всего вы должны о б ъ я в и т ь с с ы л о ч н у ю п е р е ­
в памяти массив
м е н н у ю для массива. Затем при помощи оператора new всегда хранится од­
с о з д а е т с я о б ъ е к т с указанием размера. Все готово для п о ­ ним бAOKOMJ сколь­
м е щ е н и я э л е м е н т о в в массив. Вот пример кода создания ко бы переменных
массива и вид кучи. Первый элемент массива всегда имеет в нем ни было.
нулевой и н д е к с .

Тип элементов
ИМЯ
Мйссибя heights;
heights = new int [7];
[0] = 68
[1] = 70
Вы ссыла­ [2] 63
етесь на j
элем енты < [3] = 60
массива по
индексу [4] 58
[5] = 72 ^ М а с с и в — это единый объ­
^QCOA^ ект , хотя и состоящий из
[б] = 74 семи обычных переменных.

дальше ► 177
выбираем объект из очереди

Массиб мо)кет состоять из ссылочных переменных


Массив может содержать не только числа или строки, но и ссылки
на объекты. Словом, только от вас зависит, переменные какого типа
вы хотите таким образом организовать. Можно создать как массив
Число в квадрат­
целых чисел, так и массив объектов типа Duck. ных скобках на­
Рассмотрим код создания массива из 7 переменных типа D o g . Стро­
ка инициализации создает только ссылочные переменные. За ней зывается индексом
следуют две строки new D o g {), то есть создаются два экземпляра
класса D o g . ( index) и исполь­
Dog[] dogs = new Dog [7]; Эта строка зуется для обраще­
Jk— ' объявляет
dogs [5] = new DogO; переменные,
в которых будет
ния к элементам
f dogs[0] = new DogO ; храниться
массив ссылок массива. Индекс
объекты Род.
( 7
\
первого элемента
экземпляры
(). которые пом е­
всегда равен нулю.
щаются в нулевой Т пя~
элел1ен ть/ массива.

Первая строка кода


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

о д у -

Все элементы массива являются


ссылками, в то время как
массив — это объект.

178 глава 4
типы и ссылки

Добро по)каловать на pacnpoga)ky сэндВичей о т Д}ко!


в заведении Джо множество видов мяса, хлеб на любой вкус
и больше приправ, чем вы можете себе представить. Н ет только
меню! Сможете создать для него программу, которая будет гене­
рировать меню случайным образом?
У^їражнениеі
10І МепиМакег
Randomizer
Новы й проект, содержащ ий класс М еп и М акег Meats
Для меню вам потребуются ингредиенты. Информацию о них лучше Condiments
всего хранить в виде массивов. Ингредиенты должны смешиваться Breads
случайным образом, образуя сэндвич. В этом вам поможет встроен­
ный класс R a n d o m , генерирующий случайные числа. Итак, наш класс GetiVlenultemO
будет иметь четыре поля: R a n d o m i z e r для хранения ссылок на объект
R a n d o m и три массива типа s t r i n g для информации о мясе, приправах
и хлебе. Из элементов эт их трех м ас­
сивов будет случайным образом
class МепиМакег { создаваться сэндвич.
public Random R a n d o m iz e r ;
Поле Randomizer
содержит ссы лку — " ■,
н а объект Random, string [] M e a ts = { "Roast beef , Salami^ "Turkey", "Ham", "Pastrami" };
М е т о д NextQ гене- goring[] C o n d im e n ts = { "yellow mustard", "brown mustard",
p u p y e m случайные "honey mustard", "mayo", "relish", "french dressing" };
числа.
string[] B r e a d s = { "rye", "white", "wheat", "pumpernickel",
"Italian bread", "a roll" };
^ Для доступа к элементу укажите его номер
— в скобках. Например, элемент Breads[Z] имеет
значение white.
М ето д S e tM e n u Ite m O
Наш класс должен создавать сэндвичи, поэтому добавим к нему соответствующий метод.
Это ини­ Он будет использовать метод N e x t () объекта R a n d o m для выбора элемента из каждого мас­
циализатор
коллекций,, сива. При передаче методу N e x t () целочисленного параметра он возвращает случайное
с которым вы число меньше значения этого параметра. То есть результатом работы метода R a n d o m i z e r .
подробно п о ­ N e x t (7) будет случайное число от Одо 6.
знакомитесь
в главе 8. Но как узнать, какой параметр нужен методу N e x t {) ? Он легко вычисляется при помощи
свойства массивов L e n g t h . Именно так вы получите случайный номер элемента массива.

public string G etM en u Ite m O {


string randomMeat = M e a t s [Randomizer.Next(Meats.Length)];
Метод
QetM enuttemQ. string randomCondiment = Condiments[Randomizer.Next(Condiments.Length)];
возвр айка­ string randomBread = B r e a d s [Randomizer.Next(Breads.Length)];
ет строку ■r e t u r n randomMeat + " with " + randomCondiment + " on " + randomBread;
с названием
сэндвича. }
Случайный элемент массива Meats попадает в метод randomM eat
пат ем передачи параметра Meats.Length методу Next() объекта
Random. Массив Meats состоит из 5 элементов, значит, Meats.Length
равно 5, U мет од Next(S) возвратит случайное число от О до 4.
дальше > 179
джо говорит: «не старый, а выдержанный»

Р К ^ак ЭЩО р»абогцаега.,

той
в о зв р а щ а ет число э л е м е н -
M e a ts. Т а к ч т о r a n d o m i z e r
N e x t ( M e a t s .L e n g t h ) да ем , с л ц ч а й н о е ч и гл п

> < оли 7ст в7элем ен т ов

Me a t s [ й ш 5 о т Г г е г .Ne xt (M e a t s .Length) ]
Meats - э т о массив строк, состоящий
из п я т и э л е м е н т о в . tA e a ts ^ ^
Веер’ (Ростбиф), л Meats[3j н
(Ветчина).

© Построение срормы
Добавьте к форме шесть меток и задайте свойство T ex t. Для этого воспользуй­
тесь объектом МепиМакег. Объекту потребуется присвоить начальные значения,
исп ол ьзуя н о в ы й э к зем п л я р класса Random .
^ П р и сво и т е п о л ю R a n d o m iz e r
p u b l i c F o rm l О { О б ъ е к т а М е п и М а к е г новы й
I n i tializecom ponent О ; Г х^^^сса R a n d o m .

МепиМакег menu = new МепиМакегО { Randomizer = new Random О }j A чт о будет ,


если не у к а -
labell.Text = menu.GetMenuItemO; _ за т ь начальны е
зн ачен и я п оля
labels. Text = menu.GetMenuItemO; R a n d o m iz e r ?
labels.Text = menu.GetMenuItemO; / Все готово для запуска И как эт о го
V м е т о Э й d ^ e t M e n ы it e m ( ) м ож но и зб е ­
label4.Text = menu.GetMenuItemO; Г ы получения случайного ж ат ь?
labels. Text = menu.GetMenuItemO; \ меню из шести пунктов.
label6.Text = menu.GetMenuItemO;
}

>1орру Joe's Menu


После запуска
программы шесть
мет ок п окаж ут Salami with honey m u s ta rd on rye
шесть случайных R oast beef with french dressing on v#ieat
рецептов сэндвичей. Turkey V/rith yellow mustard on wheat
Turkey with mayo on white
Pastrami vwth relish on Italian bread
Roast beef vwth french dressing on pumpernicket

180 глава 4
типы и ссылки

Ссылки позболяют объектам обращаться друг к другу

В ы у ж е в и д е л и , как ф о р м ы о б р а щ а ю т с я к о б ъ е к т а м п р и п о м о щ и с с ы л о ч н ы х
п е р е м е н н ы х , к о т о р ы е вы зы ваю т м етоды и п р о в ер я ю т зн ач ен и я п ол ей . Д ля
объ ек тов оп р ед ел ен ы те ж е оп ер ац и и , ч то и для ф о р м , потом у ч то форма —
это объект. П р и о б р а щ е н и и объ ек тов друг к другу и сп ол ьзуется к л ю ч евое
с л о в о t h i s , с е г о п о м о щ ь ю д е л а е т с я ссы л к а н а т е к у щ и й э к з е м п л я р класса.

Метод, заставляющий слона говорить


Д о б а в и м к классу E l e p h a n t м е т о д , п е р в ы м п а р а м е т р о м к о т о р о г о будет с о о б щ е н и е о т о б ъ ­
екта e l e p h a n t . В т о р ы м п а р а м етр о м будет им я слона:

public void TellMe(string message, Elephant whoSaidIt) {


MessageBox.Show(whoSaidlt.Name + ” says: " + message);

}
М ож н о добавить м етод b u t t o n 4 _ C l i c k ( ) , н о сделать эт о нуж но до оператора, переза­
гружающего ссы лки ( 1 1 o y d = l u c i n d a ;)!

lloyd.TellMe("Hi", lucinda);

М ы в ы зв а л и м е т о д T e l l M e () (С к а ж и м н е ) д л я Л л о й д а и п е р е д а л и е м у д в а п а р а м е т р а : с т р о ­
ку H i и с с ы л к у н а о б ъ е к т L u c i n d a . П а р а м е т р w h o S a i d I t ( К т о э т о с к а за л ) и с п о л ь з у е т с я д л я
д о с т у п а к п а р а м е т р у N a m e л ю б о г о с л о н а , и м я к о т о р о г о б у д е т п е р е д а н о м е т о д у T e l l M e ()
вторы м параметром.

О Вызов одного метода другим


Д о б а в и м м е т о д S p e a k T o () к к л ассу E l e p h a n t . И м е н н о з д е с ь м ы и с п о л ь з у е м к л ю ч е в о е с л о ­
во th is . О н о является ссы лк ой, позволяющей объекту рассказать о себе.
public void SpeakTo(Elephant whoToTalkTo, string message) {
whoToTalkTo.TellMe(message, this);

Э т о т м е т о д к л а с с а E le p h a n t
к-як- ч т о п я б о т я р т в(р13Ь1в а е т м с т о д T a lk T o Q
П о с м о т р и м , как э т о р а б о т а е т . (П о го в о р и с ), п о з в о л я ю щ и й о д н о м у
lloyd.SpeakToducinda, "Hello") ; слон у р а зго в а р и в а т ь с д р уги м .

П р и в ы з о в е м е т о д а S p e a k T o () д л я Л л о й д а в ы и с п о л ь з у е т е п а р а м е т р t a l k T o ( я в л я ю щ и й ­
с я с с ы л к о й н а Л ю с и н д у ) , ч т о б ы в ы з в а т ь м е т о д T e l l M e () д л я Л ю с и н д ы .

WhoToTalkTo.TellMe(message, this);
ключевое слово this
Ллойд использует ^заменяется ссылкой
WhoToTalkTo (со ссылкой на .на объект Ллойд
Люсинду) для вызова Те11Ме()

lucinda.TellMe(message, [ссылка на Ллойда]);

В результате п оя вл яется о к н о ди ал ога с о б р а щ е н и е м к Л ю си н де:

дальше > 181


болтливые объекты

Сюда объекты еще не отправлялись


с объектами связано еще одно важное ключевое слово.
Только что созданная ссылка, которгш пока никуда не указы­
вает, имеет по умолчанию значение n u l l .

Пока сущ ествует один


Dog fido; объект, ссылка fido имеет
значение null.
Dog lucky = new Dog();

Когда ссылка fido


указывает на объект, она
оольиле не равна null.

fido = new DogO;

Если присвоить lucky


значение null, объект будет
уничтожен, так как на него
не останется ссылок.

lucky = null; 5 ах! ^

/ \Л o b i« ''''

Часш'»
• Форма — это только объект? ^адаБаеМые
Что на самом деле происходит
Б оИ роС Ь !

О
с объектами после попадания в мусор?
^ ! Да! Именно поэтому код класса начи­ ! Вот для такой проверки условия:
нается с объявления этого класса. Открой­ Q ; Помните, в начале первой главы мы
те код формы и убедитесь сами. Затем if (llo y d == n u l l ) { говорили об Общеязыковой исполняю­
откройте файл P r o g r a m . c s для любой щей среде (CLR)? Это виртуальная ма­
из написанных программ и посмотрите на Оно имеет значение t r u e , если ссылка шина, управляющая всеми программами
метод M a i n O , вы найдете там строку l l o y d указывает на n u l l . •NET. Виртуальной машиной называется
new F o r m l {). способ изоляции работающих программ
Кроме того, ключевое слово n u l l от остальной оперативной системы. Вир­
Зачем мне может потребоваться позволяет быстро избавиться от туальная машина управляет используемой
ключевое слово null? ставшего ненужным объекта. Если памятью. Она следит за всеми объектами,
ссылки на объект остаются, а вам он уже и как только последняя ссылка на какой-
не нужен, достаточно воспользоваться нибудь из объектов исчезает, она освобож­
ключевым словом n u l l , и объекг будет дает оперативную память, которая была
уничтожен. выделена под этот объекг.

182 глава 4
типы и ссылки
Часзцо
Задаваем ы е
Б оИ роС Ь !

J > Я до сих пор не очень понимаю, П : я не понимаю, почему переменные Напомните мне еще раз, какую
как работают ссыпки. ^зн ы х типов имеют разный размер. ( )ункцию выполняет ключевое слово
Зачем это нужно? th is?
Q ; Ссылки — это способ доступа к мето­
дам и полям. Создав ссылку на объекг Dog, ^ ! Переменные определяют размер Q ; t h i s — это специальная перемен­
вы получаете возможность пользоваться присваиваемого значения. Если вы объя­ ная, используемая только внутри объекта.
любыми методами, определенными для это­ вите переменную типа l o n g и присвоите Она ссылается на поля и методы выбран­
го объекта. Для нестатических методов D o g . ей значение (например, 5), CLR все равно ного экземпляра. Это полезно при работе
B a r k () и D o g . B e g () можно определить выделит памяти на большое значение. с классом, методы которого обращаются
ссылку s p o t . После чего для доступа к В конце концов, на то они и переменные, к другим классам. Объект может передать
ним достаточно написать s p o t . B a r k () чтобы все время меняться. ссылку на себя другому объекту. Если
и s p o t . B e g (). Ссылки позволяют S p o t вызывает один из методов R o v e r
редакгировать поля объекта. Например, для CLR предполагает, что вы выбираете при помощи параметра t h i s , объект
внесения изменений в поле B r e e d доста­ тип осознанно и не будете объявлять R o v e r получает ссылку на объект S p o t .
точно написать s p o t . B r e e d . переменную ненужного типа. Сейчас

Получается, что редактируя


переменная хранит небольшое значение,
но потом оно может стать большим. По- •
Экземпляры объ­
объект посредством одной ссылки, этому для нее заранее выделен нужный
я меняю его значение для остальных объем памяти. ектов используют
ссылок?

Q ; Да. Если r o v e r ссылается на тот


ключевое слово this
же объект, что и spot, заменив r o v e r .
B r e e d на beagle вы получите значение
дая ссылки па са­
beagle и для s p o t . B r e e d .
мих себя.
При рассмотрении модификатора var
КЛЮЧЕВЫЕ в главе 1 4 вы узнаете, в каком случае тип
МОМЕНТЫ переменной не обьявляется заранее.

Объявляя переменную, вы ВСЕГДА указываете ее Некоторые типы могут преобразовываться друг


тип. Иногда при этом задаются и начальные значе­ в друга автоматически (например, short в int).
ния. Для других случаев используйте операцию приведе­
ния типов.
Существует множество значимых типов для хране­
ния значений разного размера. Для огромных чисел Зарезервированные слова (например, for, while,
используйте тип long — а для самых маленьких (до using, new) нельзя использовать в качестве имен
255) — bytes. переменных.

Невозможно присвоить значение большего типа пе­ Ссылки подобны наклейкам: вы можете иметь мно­
ременной, принадлежащей к меньшему типу. жество ссылок на один и тот же объект.

При работе с константами используйте суффикс F Если на объект нет ни одной ссылки, он отправляется
для обозначения типа float (15.6F), а суффикс М — в мусор, и место, занимаемое им в памяти, освобож­
для обозначения типа decimal (36.12М). дается.

дальше ► 183
возьми в руку карандаш
Перед вами массив объектов E l e p h a n t и цикл для поиска слона
с самыми большими ушами. Определите значение b i g g e s t E a r s .
E a r s п о с л е каждой итерации цикла f o r .

p r iv a te v o id b u tto n l_ C lic k (o b je c t send er, E v e n tA r g s e)

{
' 8w создаете массив
E l e p h a n t [] e le p h a n ts = n e w E l e p h a n t [7 ] из 7 ссылок ElephantQ.
e l e p h a n t s [0 ] = n e w E l e p h a n t () { Name = "L loyd " , E a rS ize =40 };
Первый индекс
e l e p h a n t s [1 ] = n e w E l e p h a n t () { Name = " L u cin d a" , E a rS ize =33 }; любого массива
e l e p h a n t s [2] = n e w E l e p h a n t () { Name = "Larry", E a rS ize =42 };
равен О,
поэтому первым
e l e p h a n t s [3 ] = n e w E l e p h a n t () { Name = " L u c ille " , E a rS ize =32 }; элементом
I Зудет
e l e p h a n t s [4] = n e w E l e p h a n t () { Name = "L ars", E a rS ize =44 }; Elephants[0].
e l e p h a n t s [5 ] = n e w E l e p h a n t () { Name = " L in d a " , E a rS ize =37 };

e l e p h a n t s [6] = n e w E l e p h a n t () { Name = "H um phrey", E a rS ize =45 };

Итерация #1 biggestEars.EarSize =
E lep h a n t b ig g e s t E a r s = e le p h a n t s [0];

fo r (in t i = 1; i < e le p h a n ts.L e n g th ; i+ + )

^ Итерация #2 biggestEars.EarSize =.
if (e le p h a n ts[i].E a r S iz e > b ig g e stE a r s.E a r S iz e )

{
b ig g e stE a r s = e le p h a n ts[i] ;
i^licpc
Итерация #3 biggestEars.EarSize =,
} Точкд останова в этой ст ро-
ке поможет отследить значения
clepkantsli] всех элементов массива.
M essageB ox. S h o w (b ig g e stE a r s. E a r S iz e . T o S tr in g ( ) ) ;
Итерация #4 biggestEars.EarSize =

Будьте внимательны, эт от цикл Итерация #5 biggestEars.EarSize =


начинается со второго элемента
массива (с индексом 1) и выполня­
ется шесть раз, пока 1 не ст ано­
вится равной длине массива.
Итерация #6 biggestEars.EarSize = _

184 глава 4
QuiBeni на с. 92*
типы и ссылки

^ а Г н и т ь ! с КоДоМ
Магниты с фрагментами кода упали с холодильника.
Верните их на место, чтобы получить код, приводящий
к появлению показанной ниже формы. refNum = index[y]; |

int refNum;

while (y < 4 ) {

resu ]_t += islands [refNumJ ,

MessageBox.Show(result);

string[] islands = new string[4]; |

result += "\nisland = "•

index =
new int f4J ;

у = Y + i

istartd = Fiji
island = C o zu m el p r iv a te v o id b u tto n l C lick frihTIZZ ^ — ---------- ------ -------------
island = B erm uda I _ -Lick ( o b j e c t s e n d e r , E ven tA rgs e)
island = Azores

OK

-------------- ► QuiBero Ha c. 93 -
магниты с кодом и ребус в бассейне

c la ss T r ia n g le
е ^ с Б бассейне
{
Возьмите фрагменты кода из d o u b le area;
бассейна и поместите их на
пустые строчки. Каждый
in t
in t
h e ig h t;
len g th ;
I K “e
фрагмент можно исполь­ p u b lic sta tic v o i d M a i n ( s t r i n g [] args
зовать несколько раз. {
В бассейне есть и лишние str in g r esu lts =
фрагменты. Нужно получить
окно, в котором для каждого
треугольника (triangle) будет по­
w h ile (
казана его площадь (area).
{
Результат: .h e ig h t = ( x + 1) * 2;
•le n g th = X + 4;

tria n g le 0, a re a 4
tria n g le 1, a re a = 1 0 resu lts += " t r i a n g l e " + x + ", area",
tria n g le 2, a re a = 1 8 resu lts += " = " + _______. a r e a + "\n " ;
tria n g le 3, a re a = _
y=__________ }

X = 27;
OK T r ia n g le t5 = ta [2 ];
t a [ 2 ] .area = 343;
r esu lts += "y = " + y ;
M e s sa g e B o x .S h o w (r e s u lts +
Дополнительный вопрос! ", t5 area = " + tB .a r e a );
Подсказка: М е­
Вспользуйтесь фрагментами из бас­ тод SetAreaQ
сейна, чтобы составить код, заполняю­ v o id setA reaO HE является
щий даже пустые поля в нижней части статическим.
окна диалога. = (h e ig h t * len g th )

К аж д ы й ф р а гм е н т кода
м о ж н о и с п о л ь зо в а ть н е ­
с ко л ь ко раз!
4, t5 area = 18
area
4, t5 area = 343
ta.area int х;
27, t5 area = 18
ta.x.area int у; X = X + 1; ta j^ ^
X ta.x.area 27, t5 area = 343
y laixj.area
ta[x].area ^ int X == 0; X = X + 2; ta(x)
int X == 1; ' X = X -1;
Triangle [ ] ta = new Trlangle(4); setArea(); ta[x]
int у == x;
Triangle ta = new [ ] Triangle[4]; ta.x = setArea(); ta = new TriangleO;
28
Triangle [ ] ta = new Triangle[4]; ta[x].setArea(); ta[x] = newTriangleO
30.0
^ ta.x = new TriangleO;

О хпБ еш на С.
186 глава 4
типы и ссылки

играем 6 печатную машинку


Вы достигли первых результатов... и знаете достаточно, чтобы создать собственную
игру! Пусть в форме случайным образом появляются буквы. Если игрок вводит букву
правильно, она исчезает, а уровень растет. Если же буква введена неправильно, уровень
уменьшается. По мере ввода букв игра усложняется. Как только форма оказывается за-'у' / |
полнена буквами, игра заканчивается! \ ^

H it th e к в у іїЗ

и К К N С
C otrect, 18 M issed-3 Total: Д A ccuracy; 85%

^ іо р м а
Вот как она должна выглядеть в конструкторе форм.

listBoxI
Correct О Total: О Accuracy: 0 %

Уберите кнопки управления размерами окна. Для свойства FormBorderStyle выберите


вариант FixedSD. Теперь игрок не сможет случайно перетащить форму и изменить ее
размер. Установите размер 876 X 174.
Перетащите из окна Toolbox на форму элемент управления ListBox. Присвойте свой­
ству Dock значение Fill. Свойству MultiColimm присвойте значение True. Для свойства
Font выберите кегль 72 пункта и полужирное начертание.
В окне Toolbox раскройте группу All Windows Forms. Найдите элемент управления Timer
и дважды щелкните на нем, чтобы добавить его к форме.
Затем найдите элемент управления StatusStrip и двойным щелчком добавьте к форме
строку состояния. В нижней части конструктора формы должны появиться значки эле­
ментов управления StatusStrip и Timer:

0 timerl statusStripl
J
дальше * 187
создадим что-нибудь забавное

О Параметры элемента управления StatusStrip ІССЛАРТКЇ)


Обратите внимание на первый рисунок данного
раздела. В нижней части строки состояния вы Вы познакомились с тремя
увидите метки: новыми элементами управления!
Задать свойства для ListBox,
I Correcte 18 M t5sedi3 T o ta b Z t A c c u f a ^ 8 5 % |
StatusStrip и Timer вы сможете зна­
комым способом.
★ A с другой стороны —метку и индикатор:
I Difficulty Ь ю у у ж

Щ елкните на стрелке справа от элемента управления


S t a t u s S t r i p и выберите в появившемся меню вариант
S ta tu s L a b e l
S ta tu sL a b el:
P rogressB ar

D ro p D o w n B u tto n

Ш SplitButton

★ Свойству S i z i n g G r ip элемента S ta tu sS tr ip присвойте значение False.


★ В окне Properties присвойте свойству ( N a m e ) значение c o r r e c t L a b e l , а свойству T e x t
значение Correct: О (Правильных: 0). Добавьте три аналогичные метки: m i s s e d L a b e l ,
t o t a l L a b e l и a c c u r a c y L a b e l (Пропущенных, Всего и Точность).

★ Добавьте S ta tu sL a b el. Укажите для S p r i n g значение T r u e , для T e x t A l i g n значение


M id d le R ig h t и для T e x t — D i f f i c u l t y (Сложность). Напоследок добавьте элемент
P ro g r ès sB ar и присвойте ему имя d i f f і c u l t y P r o g r e s s B a r .

О Параметры элемента управления Tim er.


Вы заметили, что элемент управления Timer на форме отсутствует? Дело в том, что это не-
визуалъный элемент управленім. Он не меняет вида формы. Его функция снова и снова вы ­
зы вать некий метод. Присвойте свойству I n t e r v a l значение 800, чтобы вызов метода про­
исходил каждые 800 миллисекунд. Затем дваж ды щ елкните на значке timerl в конструкторе,
чтобы добавить к форме метод tim e r l_ T ic k . Вот код для этого метода:
p riv a te v o id tim e r l_ T ic k (o b je c t sen d er, E ven tA rgs e)

/ / Д обави м с л у ч а й н у ю клавиш у к э л е м е н т у L i s t B o x
l i s t B o x l . I t e m s .A d d ( ( K e y s ) r a n d o m . N e x t ( 6 5 , 9 0 ) ) ;
Скоро вы добавите
i f ( l i s t B o x l . I t e m s . C o u n t > 7)
поле гап(£от. Мо­
жете ли вы сейчас
{ назвать его тип?
lis tB o x l.Ite m s.C le a r 0 ;
l i s t B o x l . I t e m s . A d d ( "Игра окончена!");
t im e r l. S to p ();
}

188 глава 4
типы и ссылки

Класс, отслеживающий статистику игры


Так как в форме должно отображаться общее количество нажатых, пропу­
щенных и правильно нажатых клавиш, а также точность, значит, мы долж­
ны отслеживать все эти данные. Кажется, нам потребуется новый класс!
Назовите его S t a t s . Он будет содержать четыре поля типа i n t с именами
T o t a l (Всего), M i s s e d (Пропущено), C o r r e c t (Правильно) и A c c u r a c y
(Точность), а также метод U p d a t e с одним параметром типа b o o l , кото­
рый получает значение t r u e , если нажатая игроком клавиша совпала с бук­
вой, появившейся в окне ListBox, и значение f a l s e , если игрок ошибся.

c la ss S ta ts
{
p u b lic in t T o t a l = 0;
p u b lic in t M is s e d = 0;
p u b lic in t C o r r e c t = 0;
p u b lic in t A c c u r a c y = 0;

p u b lic v o id U p d ate(b ool correctK ey)


{
T o t a l ++;

if ( ! correctK ey)
{
M isse d + + ; При каждом вызове метода
} UpdateQ вычисляется про­
e ls e цент правильных попаданий,
{ а результ ат эт их вычислений
C o r r e c t ++; помеицается в поле Accuracy.
}
A c c u r a c y = 100 * C orrect / (M isse d + C orrect) ;
}
}
Поля для отслеживания объектов S tats и Random
Вам потребуется экземпляр класса Stats для хранения информации, поэтому добавьте поле
stats. Как вы уже видели, поле random, содержащее объект Random, пока отсутствует.

Напишите в верхней части кода формы:


Прежде чем продолжить, присвойте свойству
p u b lic p a r tia l c la ss Form l : Form Enabled таймера значение True. Для элемента
{ ProgressBar сделайте свойство Maximum
Random random = new Random(); равным 701, а для свойства KeyPreview
Stats stats = new Stats(); формы выберите значение True. Попробуйте
ответить на вопрос, что будет,
если это не сделать?

дальше ► 189
ключ к прекрасной игре

Контроль за нажатием клавиш.


Осталось сделать так, чтобы правильно нажатая игроком буква удалялась из окна ListBox),
а статистика S t a t u s S t r i p обновлялась. Эта кнопка меняет
вид окна Properties.
Вернитесь к конструктору форм и выделите Properties
Кнопка слева от
форму. Щ елкните на кнопке с изображением Forml System.Wim нее возвраш,ает
молнии в верхней части окна Properties, а за­
тем дважды щелкните на строчке KeyDown,
О' !
InputlanguageChdf
окно к привычноми
виду.
n l.K e y O sm i Ц
чтобы добавить метод Forml_KeyDown (), вы­ KeyPfess Вы получаете
зываемый при каждом нажатии клавиши. Вот KeyUp
список событий
код для этого метода: (events). О т ом,
что это такое,
p r i v a t e v o i d F o rm l_ K ey D o w n (o b je c t s e n d e r , K ey E v en tA rg s e) мы поговорим
{ позднее.
Оператор П Е с л и п о л ь з о в а т е л ь п р а в и л ь н о наж и м а е т клавишу, у д а л и т е б у к в у из L i s t B o x ,
if проверя­
ет н а л и ч и е ^ и и у в е л и ч ь т е с к о р о с т ь п о я в л е н и я б у к в
в ListBox на­ i f ( l i s t B o x l . I t e m s . C o n t a i n s ( е . K e y C o d e ) )
жатой игро­ {
ком буквы. l i s t B o x l . Ite m s.R e m o v e (e . K eyC ode);
l i s t B o x l .R e fr e sh ();
i f (tim e r l. In terval Уменьшая числа, вычитаемые из
tim e r l. In terval парамет ра timeri-.Interval, вы
i f (tim e r l. In terval облегчаете игру, а увеличивая —
tim e r l. In terval усложняете ее.
i f (tim e r l. In terval
tim e r l. In terval
d iffic u lty P r o g r e ssB a r .V a lu e = 800 - tim e r l. In te r v a l;

При нажа­ / / При правильном нажатии клавиши обновляем объект S t a t s ,


тии клавиши / / в ы з ы в а я м е т о д U p d a t e () с а р г у м е н т о м t r u e
метод Forml. s ta ts .U p d a te (tr u e );
KeyPown() }
вызывает м е ­ e lse
тод UpdateQ {
объекта Stats, // П р и н е п р а в и л ь н о м н а ж а т и и к л а в и ш и о б н о в л я е м о б ъ е к т S t a t s ,
обновляющий // в ы з ы в а я м е т о д U p d a t e () с а р г у м е н т о м f a l s e
ст ат ист и- s ta ts .U p d a te (fa ls e );
ку, а зат ем ''
р езуль­ }
т ат от о-
6J}aжaemcя / / Обновление меток элемента S t a t u s S t r i p
StatusStrip. c o r r e c t L a b e l . T e x t = " C o r r e c t : " -i- s t a t s . C o r r e c t ,•
m i s s e d L a b e l . T e x t = " M issed : " + s t a t s . M is se d ;
t o t a lL a b e l.T e x t = " T o ta l: " + s t a t s . T o t a l ;
a c c u r a c y L a b e l. T ext = "A ccuracy: " + s t a t s .A c c u r a c y +

Запуск игры.
В окно ListBox должно помещаться ровно 7 букв, поэтому может потребоваться поменять
размер шрифта. Для изменения уровня сложности отредактируйте значения вычитаемые из
параметра t i m e r l . I n t e r v a l в методе F o r m l _ K e y D o w n ( ) .

190 глава 4 ★ -
типы и ссылки

Е щ е раз напомним, что в С # сущ ествует примерно 77 з а р е з е р в и р о в а н ­


н ы х сл о в . Вам бы ло предлож ено объяснить назначение некоторых из
г^р аж н ен и б
них. Вот правильны е ответы.
решение
namespace Пространство имен — это логическое понятие, объединяюи^ее
связанные друг с другом классы и типы.

for Это цикл, выполняющий оператор или блок операторов, пока


определенное выражение не прим ет значение false.

Класс —- это определение объекта. Классы имею т


class свойства и методы.

Ключевое слово, дающее уровень доступа с максимальными правами.


public Public class может использоваться любым другим классом.

else Оператор, который выполняется, если проверка условия if вернула


значение false.

while Цикл while выполняется до тех пор, пока условие имеет значение
true.

using Определяет пространства имен, предустановленные и созданные вами


классы, которые используются в программе.

if Оператор, выбирающий другие операторы по результ ат ам


проверки условия.

new Оператор, создающий новый экземпляр объекта.


решение упражнения

озьми в руку карандаш


’ешение Вот как выглядят результаты определения самого боль­
шого слоновьего уха на каждой итерации цикла for.

p riv a te v o id b u tto n l_ C lic k (o b je c t send er, E ven tA rgs e)

{ П ом ните, 41^0
E l e p h a n t [] e le p h a n ts = new E l e p h a n t [ 7 ]; цикл НйИиНйбИЛСЯ
со второго эле­
e l e p h a n t s [0] = n e w E l e p h a n t () { Name = " L l o y d " , E a rS ize =40 }; мента т с с м а .
К ак 6(?| Эуллаете,
e l e p h a n t s [1 ] = n e w E l e p h a n t () { Name = " L u c i n d a " , E a rS ize =33 }; почему?
e l e p h a n t s [2] = n e w E l e p h a n t () { Name = " L a r r y " , E a rS ize =42 };

e l e p h a n t s [3] = n e w E l e p h a n t () { Name = " L u c i l l e " , E a rS ize =32 };

e l e p h a n t s [4] = n e w E l e p h a n t () { Name = " L a r s " , E a r S i z e = 44 };

e l e p h a n t s [5 ] = n e w E l e p h a n t () { Name = " L i n d a " , E a rS ize =37 };

e l e p h a n t s [6] = n e w E l e p h a n t () { Name = " H u m p h r e y " , E a rS ize = 45 }

Итерация #1 biggestEars.EarSize = 4 0
E lep h a n t b ig g e s t E a r s = e le p h a n t s [0];

for (in t i = 1; i < e le p h a n ts.L e n g th ; i+ + )

{
Итерация #2 biggestEars.EarSize = 4 2
if ( e l e p h a n t s [ i ] . E a rS ize > b ig g e stE a r s.E a r S iz e )

Ссылка
{
b ig g e stE a r s = e le p h a n ts [i] ;
t biggestEars
отслеживает
самый боль - Итерация #3 biggestEars.EarSize =
42,

} Поместите сюда точку элемент


— останова для проверки g ц^кле.
>} результат а.
M e s s a g e B o x .S h o w (b ig g e stE a r s .E a r S iz e .T o S tr in g ());
Итерация #4 biggestEars.EarSize =

иОЛОШ^, .. - .......
/ Итерация #5 biggestEars.EarSize =

нает указывать нд него. Таким


образом определяется слон с са­
мыми большими ушами.
•4 -S
Итерация #6 biggestEars.EarSize = _____

192 глава 4
типы и ссылки

|^е1Нение Задачи сг МаГнишаМи


Вот каким образом нужно было расположить на хо­
лодильнике магниты с фрагментами кода.

f ^ c b задаются
^лчальные
значения
массива fndexli

Здесь задаются
начальные значения
массива 1$1апи51].

Итоговая строка
составляется
in t refN u m ; | при помощи
оператора +=■
w h i l e ^ (y < 4) { P
while
^^^Менилы
retN um = in d ex [y ];
^^ссива indexn
r esu lt += " \n isla n d = 1

r esu lt += i s l a n d s [ r e f N u m ] ; J
island = Fiji
island = C o zu m e l
island = B erm u da
island = Azores

дальше > 193


решение ребуса

еШ ен и е ]= * е^ са Б б а с с е й н е

Вы зам ет или, что класс


им еем мочку входа и при
эт ом создаем экземпляр
r себя? В С* такое вполне
c la ss T r ia n g le допусмимо.
{
d o u b le area;
in t h e ig h t;
in t len g th ;

После э т о й строки p u b lic sta tic v o i d M a i n ( s t r i n g [] args)


вы получаете массив {
из четырех ссылок strin g r esu lts =
Trian gle, но пока нет i n t X = O;
ни оЭного оЗьекта___ Triangle[] ta = new Triangle[4]; Цикл while
Triangle! создает чет ы -
w h ile ( X < 4 )
ре экземпляра
{ Triangle, чет ы ­
ОтВеш на дополнитель­ ta[x] = new TriangleQ) ре раза вызывая
ный Вопрос: ta fxl -h eig h t = (x + 1 ) * 2 ; оператор new.
ta fxl . le n g th = x + 4 ;
ta[x].setAreaQ;_____
r esu lts += " tr ia n g le " + x + area"
r e s u l t s += = " + ta fxl .area + " \n " ;
trtangte 0, area = 4 X = X + 1;

triangle 1, area = 10 }
triangte 2, area = 18 i n t у ~ x;

triangle 3, area = z s X = 27;

V = 4^ ts a r e a = 3 4 5 T r ia n g le t5 = ta[2];
t a [2 ] . a r e a = 343;
resu lts += "y = " + y ;
M e s sa g e B o x .S h o w (r e su lts +
OK ", t5 area = " + tS .a r e a );
}
v o id setA reaO
{
area = (h eig h t * len g th ) / 2;
Метод setAreaQ использу­
ет поля height и length для
вычисления значения поля }
area. Так как мет од не
является стат ическим, он
может вызываться только
для экземпляра Triangle.

194 глава 4
5 инкапсуляция

Пусть личное остается...


личным

Вы когда-нибудь мечтали о том, чтобы вашу личную жизнь


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

Кэтлин профессиональный массобик-затейник


Она организует великолепные званые ужины.
Н о для нее настали тяжелые времена, так как
по мнению клиентов Кэтлин недостаточно
стро называет стоимость услуг.

5юЭжет.

После получения от нового клиента информации о количестве участ­


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

196 глава 5
инкапсуляция

Как происходит оценка


Вот фрагмент записей Кэтлин, касающийся расчетов
стоимости мероприятия:

О и е н к а стои м ости обеда

За каждого гостя — $25.


Большинство обедов сервируется с алкогольными напитками — это
дополнительные $20 на человека. Можно выбрать «здоровый» ва­
риант - это стоит всего $5 на человека, вместо алкоголя подаются
соки и газировка. «Здоровый» вариант намного проше в организа­
ции, поэтому скидка составит 5% на всю стоимость мероприятия.
. Обычное оформление стоит $7.50 на человека плюс первоначаль­
ный взнос $30. Стоимость особого оформления увеличивается до
$15 на человека, а первоначальный взнос составит $50.

В некоторых случаях
меняется не только
стоимость на одного
Для наглядности представим эти правила в виде гостя, но и общая цена
диаграммы: мероприятия.

$5
на человека-«^ $15 на че­
5% скидки ловека
с общей +ВЗНОС
суммы $50
Кол ичество О собо е
гостей «Здоровы й» чштшшлштт
ч оф о р м л е­
Еда ($2Ь вариант? ние?
на человека)
Нет ч
$20 с ч ел о ­ $7.50 на ^
века
человека 1
+взнос$30 1

г
Выбор этого варианта
не только влияет на ст о­
имость за одного человека,
но и включает единовре­
менный взнос.

дальше > 197


ok, нет проблем

Создадим программу, оценивающую стоимость обедов.


нение
Создайте проект Windows Application, добавьте класс D in n e rP a rty .c s
и оформите его в соответствии с показанной слева диаграммой. Ме­
тоды затрачивают расчеты стоимости «здорового» варианта, сто­
имости оформления, а также общей стоимости мероприятия. Два
последних поля должны принадлежать типу d e c im a l, а первое —
Dinnerparty типу i n t . Убедитесь, что в конце каждой константы типа d e c im a l
стоит б у к в а м (например, 10 . ОМ).
NumberOfPeople
CostOfBeveragesPerPerson @ Так как стоимость еды на одного человека не будет меняться, ее
CostOfDecorations можно объявить как консгттту. Вот как это делается:
p u b lic const in t C ostO fF oodP erP erson = 25;

SetHealthyOptionO e Один из методов возвращает значение типа d e c im a l, два дру­


CalculateCostOfDecorationsO гих — нет. Метод C a lc u la te C o s tO f D e c o r a tio n s O вычисляет
CalculateCostO стоимость оф ормления в зависимости от количества пригла­
шенных. Метод C a l c u la te C o s t () вы числяет общую стоимость,
складывая цену оф ормлениы , еды и напитков в зависимости от
количества приглащенных. П ри выборе здорового варианта де­
лается скидка с общей стоимости.

Добавьте к форме код:


Вы объявляете поле
Dinnerparty dinnerparty; dinnerparty и добавляете
p u b lic F o rm lО { четыре строчки.
In itia liz e C o m p o n e n tO ;
dinnerparty = new DinnerParty() { NumberOfPeople = 5 };
Рямет р dinnerparty.SetHealthyOption(false);
обновления SHauff dinnerparty.CalculateCostOfDecorations(true);
DisplayDinnerPartyCost0;
>

О Форма должна выгля-


деть так. Используйте
^

элемент N um ericUpDown, ццсА®


Party Planner
чтобы задать максималь-
Код using System. ное количество людей ~~~ Number rf People
VJindows.forms: для
класса Dinnerparty
равным 20, а минималь­
ное — 1. По умолчанию Свойство
^ it

не требуется, т ак [V] Fancy Oeceathms


количество приглашен- ^l^ccked
как вы не собираетесь Ej H eÄ yO f*«!
(^спользовать м е т о ­ ных равно 5. Избавьтесь t t Z a t i o n ^ ^
ды из пространства от кнопок управления должно имет ь Cost i
имен .NET Framework. размерами окна. значение True.

Имя этой м ет ки labelCost. Свойство Text оставлено


пуст ым, свойство BorderStyle имеет значение--------
FixedsD, а свойство AutoSize значение false.
198 глава 5
инкапсуляция

О Сделаем так, чтобы итоговая сумма автоматически менялась при изменении


флажков и показаний счетчика Ыитег1сирВо1А?п. Для этого вам потребуется ме­
тод, отображающий сумму.
Добавим его к Forml ( ). O h будет вы зы ваться при щ елчке на элем енте
Этот hAtmob вызы­ NumericUpDown:
ваемся всеми м е - Метод рассчитывает ст о-
тоЗаМи, связанными
p r iv a te v o i d D i s p l a y D i n n e r P a r t y C o s t ()
с формой, именно " р езул ьт ат м е т к е Cost.
т а к обновляется {
з н а ч е н и е м е т к и C ost. d e c im a l C o st = d i n n e r p a r t y .C a l c u la t e C o s t ( c h e c k B o x 2 . Checked)
c o s t L a b e l. T ext = C o s t.T o S tr in g (" c " );

Присвойте мет ке,


А ргум ент "с” метода
t Значение true появля-
отображающей
цену, имя costLabel. ToStringO отображает в а л ю
с использованием приня- Healthy Option,
того по соглашению символа.

О Соединим поле NumericUpDown с переменной N um berO fPeople, принад­


лежащей классу D in n e r p a r ty , чтобы в ф орме начала отображ аться сумма
При двойном расходов. Дважды щ елкните на элементе NumericUpDown, в код будет до­
щелчке на
кнопке ИСР бавлен обработчик событий (event handler). Так называется метод, запускае­
добавляет об­ мый при каждом изменении элемента управления. Он сбросит количество
работчик со­ гостей. Впишите следующий код:
бытия Click. p riv a te v o id n u m ericU p D o w n l_ V a lu eC h a n g ed (
o b ject sen d er, E ventA rgs e)
{
d in n e rp a rty .N u m b erO fP eo p le (i n t ) n u m ericU p D ow n l. V a l u e ;
^ D isp la y D in n e r P a r ty C o st();
J C_ Значение numericUpPown-Value
принадлежит т ипу Decimal,
поэт ому требуется операция
приведения типов.
Ой... код содержит ошибку. Вы ее видите? Если нет, не волнуйтесь. Скоро мы
все объясним!
Из формы методу Первый мет од рассчит^.,а
передается л о - ^ ^ ^ ‘^Мость
гическое значение \ второй
fancyBox.Checked. конечную сум м у в форме.

Дважды щ елкните на флаж ке(РапсуВесога11оп5’у убедитесь, что


сначала он вызывает метод C alcu iacscC ig iC C fD ecS ratio n s (), а по­
том метод D lsp la^ d iiB i^ erP arty C G S t (). Затем дважды щелкни­
те на флажке ^Healthy O ption? и убедитесь, что он сначала вызыва­
ет метод S e t H e a l t h y O p t i o ^ ) класса D in n e rP a r ty , а затем метод
D is p la y D in n e r P a r ty C o s t ( ) /

дальше > 199


решение упражнения

В от такой код дол ж ен содерж аться в ф айле D i n n e r P a r t y . c s .


т нш
И сп ользован и е конст ант , га р а н т и р у ­
е м , ч т о данны е п а р а м е т р ы о с т а н у т ­
ся н е и з м е н н ы м и н а п р о т я ж е н и и в с е й
п рогр ам м ы .
c la ss D in n erP a rty {
const in t C ostO fF oodP erP erson = 25; Создав объект, форма ис­
p u b lic i n t N u m b e rO fP eo p le ; пользует инициализатор
для указания параметра
p u b lic d e c im a l C ostO fB everagesP erP erson;
NumberOfPeople. Зат ем м е ­
p u b lic d e c im a l C o stO fD eco ra tio n s = 0; тоды SetHealthyOptionO
и CalculateCostOfDecorationsO
p u b lic v o id S e tH e a lth y O p tio n (b o o l h ea lth y O p tio n ) { задают значения других полей.
if (h ea lth y O p tio n ) {
C o s t O f B e v e r a g e s P e r P e r s o n = 5.00M ;
} e ls e {
C o s t O f B e v e r a g e s P e r P e r s o n = 2 0 .00M ; Оператор i f в с е г д а п р о в е р я е т , CO
5 л ю д а ет с я ли у с л о в и е , п о э т о м у
}
д о с т а т о ч н о н а п и с а т ь " if ( F a n c y ) ”
}
в м е с т о " if ( F a n c y = - t r u e ) ”.

p u b lic v o id C a lcu la teC o stO fD eco ra tio n s(b o o l fancy) {


if (fan cy)

{
C o stO fD eco ra tio n s = (N u m b erO fP eo p le * 1 5 .00M ) + SOM;
} e ls e {
C o stO fD eco ra tio n s = (N u m b erO fP eop le * 7.50M ) + 30M;
}
}
p u b lic d e c im a l C a lc u la te C o s t(b o o l h ea lth y O p tio n ) {
d e c im a l to ta lC o st = C o stO fD eco ra tio n s +
( (C o stO fB e v er a g e sP er P e r so n + C ostO fF oodP erP erson )
N u m b erO fP eo p le)
^ М ы и сп о л ьзо ва л и скобки , ч т обы г а -
ран т и роват ь прави льн ост ь м а т е ­
if (h ea lth y O p tio n ) {
м а т и ч е с к и х вы чи слен и й .
retu rn to ta lC o st .95М ;
} e ls e {
retu rn to ta lC o st;

} S % -я ск и дк а п р и у с л о в и и ,
ч т о обед п о д а ет ся без а л -
к о го л я .

200 глава 5
инкапсуляция

Д ля переменных, содержащих цены, выбирается тип d ecim a l. Всегда помещайте букву М


после цифры: чтобы присвоить переменной значение $35.26, нужно написать 3 5 . 2 6М. Это
легко запомнить, потому что М —первая буква в слове money (деньги)!

p u b lic p a r tia l c la s s Form l : F orm { DisplayDinnerPartyCost пере-


/-■ Оаепл. оанные мет.ке, которая от о-
D in n erP a rty d in n e r p a r ty ; / бражает сум м у расходов сразу после
p u b lic F orm iO { / загрузки формы.
In itia liz e C o m p o n e n tO ;
d in n erp a rty = n e w D i n n e r P a r t y () { N u m b e rO fP eo p le = 5 };
d in n e r p a r ty .C a lc u la te C o stO fD e c o r a tio n s(fa n c y B o x .C h e c k e d );
d in n e r p a r ty . S e tH e a lth y O p tio n (h e a lth y B o x .C h e c k e d );
D isp la y D in n e rP a r ty C o st 0 ; флажки меняьот значение перем ен-
} healthyOption и Fancy с true на
false и обратно.
p riv a te v o id fan cyB ox_C h eck ed C h an ged (ob ject send er, E ven tA rgs e) {
d in n e r p a r ty .C a lc u la te C o stO fD e c o r a tio n s(fa n c y B o x .C h e c k e d );
D isp la y D in n e r P a r ty C o st0 ;
Мы присвоили флажкам имена healthyBox
и fo.t\cyЗoxJ Ч1/\лоды вш м о 2ли чидо 1^ роис~
ходит в их методах обработчиков событий.
p r iv a te v o id h e a lth y B o x _ C h ec k e d C h a n g ed (o b jec t send er, E ven tA rgs e) {
d in n e r p a r ty . S etH ea lth y O p tio n (h ea lth y B o x .C h eck ed );
D isp la y D in n e r P a r ty C o st();

p riv a te v o i d n u m ericU p D o w n l_ V a lu eC h an g ed (o b ject sen d er, E ven tA rgs e) {


d in n e rp a rty .N u m b erO fP eo p le = (in t)n u m e r ic U p D o w n l.V a lu e ;
D isp la y D in n e rP a r ty C o st 0 ; ^ -------- СуМма
должна
tv'V"/»/-I"»* пересчитываться
---- -
и отображаться при каждом изм е-
J у^ '
нении количества гостей и1. каждой
^ л■• л (УЛ ЧА/ ЛЛ t~
i
V- установке флажка.
p r iv a te v o id D isp la y D in n e r P a r ty C o stО {
d e c im a l C o st = d in n e r P a r ty .C a lc u la te C o s t(h e a lth y B o x .C h e c k e d );
c o stL a b e l.T e x t = C o s t. T o S tr in g ( "c");

Метод ToStringQ преобразует переменные в строки. Аргумент при


этом преобразуется в локальную денежную единицу. Аргумент "ft5”
форматирует результат в виде типа decimal с тремя знаками после
запятой^ (ноль) превращает результат в целое число, "0%” — в це­
лое с процентами, а "п” дает число с запятой в качестве разделителя
групп разрядов. Вы сами можете посмотреть, как это работает!

дальше > 201


что-то пошло не так

Кэтлин те сти р уе т программу


г, S и з AhoSuMfIX к л и
лй К э т л и н . Она о р г а и ы з о -
Потрясающе! Как
быстро я теперь могу
назвать сумму! бйние званого обеда.

Роб (по телефону): Привет, Кэтлин! Как там под­


готовка моей вечеринки? флажок Fancy Decorations
установлен по ум олча-
Кэтлин: Великолепно. Мы уже заказали оформле­ HUhOj так как его свойство
ние. Тебе должно понравиться. Checked имеет значение
true. Если количество го­
Роб: Фантастика! Послушай, мне только что по­ стей равно Ю , стоимость
звонила тетя жены. Она с мужем собирается пого­ обеда составит $575.
стить у нас пару недель. Сколько будет стоит вклю­
чение в список гостей еш;е двух человек?
Кэтлин: Подожди минутку...

ш P arty P la n n e r
Изменив парамет р
Number rf People Number of People с l o
12 на IZ j в итоге п о лу­
Fancy DecoraJtons
чаем $б&5. Сумма
кажется ей слишком
H He^hyC^ton маленькой...
Coat !№65:00

Кэтлин: Кажется, общая стоимость обеда возрас­


тет с $575 до $665.
Роб: Всего на $90? Соблазнительно! А какая цена
получится, если убрать особое оформление?

202 глава 5
инкапсуляция

'iff Party Planner

МшЛег«# Peofrfe
Снятие флажка
Рапсу Decorations Ратсу OecOTthjns

s r s a r
^пакого не может!
Healthy Option

Coat | ii«6b.00

Кэтлин; Ээээ... получается сумма в $660.


Роб: $660? Я думал, оформление стоит $15 с человека. Вы что, поменяли цену?
Если разница составит всего $5, оставим особый вариант. Хотя, должен заме­
тить, что в твоих ценах я уже запутался.
Кэтлин: Я только что получила новую программу для оценки расходов. Но
кажется, она где-то ошибается. Подожди секунду, я попробую снова добавить
к счету особое оформление.

Itete-rfPes^jte
12
g ] Fancy DecotaHws
не Эол>кно!
H HeafchyOptiOTi

Кэтлин: Роб, произошла ошибка. С особым оформлением цена возрастает до


$770. Что-то я не доверяю этому приложению. Верну-ка я его на доработку и по­
считаю вручную, как и раньше. Я могу позвонить тебе завтра?
Роб: Я не готов платить $770 за двух дополнительных гостей. Сначала ты озву­
чила мне намного более разумную цену. Я дам $665 и ни центом больше!

ШТУРМ
Как вы думаете, почему каждое изменение условий давало ошибку в результате?

дальше У 203
неожиданно оказалось, что...

Ка)кдьш бариант ну)кно было счи тать АССЛ^?Т)ТК1)


отдельно Это не ваша вина!
В код специально была помеще­
Подсчет сумм велся строго по диаграмме Кэтлин, но мы не учли на ошибка, чтобы показать, ка­
того, каким образом на общий счет влияет изменение каждого кие проблемы возникают, когда
параметра формы. объекты используют поля друг
друга, и то, как сложно эти про­
При запуске формы количество гостей по умолчанию равно
блемы отследить.
5, кроме того, установлен флажок Fancy Decorations. Флажок
Healthy Option не установлен. При этих условиях стоимость ме­
роприятия равна $350. Вот как получается эта сумма:

«в Party Planner
5 человек
Nwnbe-of Peof^e
$20 с человека за напитки С тоим ость напитков = $100
$25 с человека за ед у -— С тоим ость еды = $125 Farwy O ecw afior»

$15 с человека за —----------- С тоим ость оф ор м л ения = $125 He^qrOjjBon


оф ор м л ение и взнос $50 Cost ^OKa все
‘^Р^вильно.
a j
$ 1 0 0 + $ 1 2 5 + 125 = $350

П ри изменении количества гостей приложение должно пересчи­


тывать сумму аналогичным образом. Но этого не происходит:

10 человек
Щ Party Planner
$20 с человека за напитки С тоим ость напитков = $200
Рес^
$25 с человека за ед у —- - V С тоим ость еды = $250
$15 с человека за ------------- ^ С тоим ость оф ор м л ения = $200 Н Fmc^ Оеояйюпз
оф орм л ение и взнос $50 В НеЛуйэеоп
Сол
$200 + $250+ 200 = $650

Снимите флажок Fancy Deco­


rations и проверьте результат. Программа складывает
'^^^лунит.ь. старцю иенц оформления
Поле объекта
C o stO fD ec o ra tio n s
с новьши ценами еды
обновится, и вы полу­
D in n er P a rty и напитков.
чите правильную сумму $650. + ^3-2.5= $575.
t У ' ^
Нена еды С тар ая цена
204 глава 5 ^»1^итков. оформления.
инкапсуляция

П р о б л е м а Ц оД у В е Л и Ч ш п е Л ь Н ь їМ с т е И І о М

Рассмотрим метод, обрабатывающий изменение состояния элемента


n u m e r i c U p D o w n . Он берет значение переменной N u m b e r o f P e o p l e и вы­
зывает метод D i s p l a y D i n n e r P a r t y C o s t О . Именно здесь осуществляет­
ся пересчет конечной суммы.
p r iv a te v o id n u m er icU p D o w n l_ V a lu e C h a n g ed
Эта строка
ob ject sender, E ven tA rgs e) {
задает значе­
d in n e r P a r ty .N u m b e r o fP e o p le = (in t)n u m e r ic U p D o w n l.V a lu e ;
ние параметра
l^umЬerofPeopie■
D isp la y D in n e r P a r ty C o st(); Эля экземпляра
ріппсграгіу на
1 Аанный m m o d вызывает метод основе введенных
' CalculateCostO, но забывает вызвать
мет од CalculateCostofPecorationsO- в форму данных.

То есть при изменении значения в поле N u m b e r o f P e o p l e


показанный ниже метод никогда не вызывается:

p u b lic v o id C a lcu la teC o stO fD eco ra tio n s(b o o l Fancy) {


Эта переменная сохраняет
if (F ancy) { значение полученное
при первом вызове формы.
C o stO fD eco ra tio n s = (N u m b erO fP eop le * 1 5.00М ) + 50М;

} e ls e {

C o stO fD eco ra tio n s = ( N u m b e r O f P e o p l e * 7 . SOM) + 30M;

Повторная установка флажка Fancy


} Pecorations снова запускает метод
CalculateCostOf PecorationsQ, что
приводит к коррекции данных.

Предполагалось, что все


три варианта будут выбираться
одновременно!

...иногда этими
К сожалению, пользователи не всегда исполь­ «пользова теля -
зуют классы так, как предполагал разработчик. м и » являетесь
К счастью, в C# есть функция, позволяющая га­ вы сами!
рантировать корректную работу программы, даже
когда пользователь делает вещи, о которых вы и
предположить не могли. Она называется инкапсу­
л яцией (encapsulation).

дальше ► 205
защити свои объекты

Неправильное использование объектов


Программа не принесла Кэтлин пользы, так как форма, проигнорировав метод
C a l c u l a t e C o s t O f D e c o r a t i o n s О , сразу перешла к полям класса D i n n e r P a r t y .
Этот класс написан без ошибок, но программа все равно работает некорректно.

Как нужно было бы вызывать класс DinnerParty


Класс D i n n e r P a r t y предоставляет форме прекрасный метод расчета
конечной стоимости оформления. Достаточно указать количество го­
стей и вызвать метод C a l c u l a t e C o s t O f D e c o r a t i o n s (), после чего
метод C a l c u l a t e C o s t {) покажет правильную сумму.

NumberOfPeople = Ю;
CalculateCostOfDecorations(true)

C a lc u la te C o stO retu rn s $650

о этот класс на самом деле вызывается


После указания количества гостей форма сразу вызывает метод
C a l c u l a t e C o s t O , игнорируя расчет стоимости оформления. То
есть пропускается целый этап, и в итоге получается неверная сумма.

NumberOfPeople - 10;

C a l c u la te C o s t O возвращ;ает$575
Метод CalculateCostO
\ возвращает значение,
но К эт лин не может
знать, что результ ат
расчетов некорректен.

206 глава 5
инкапсуляция

инкапсуляция как управление доступом к данным


В С* поля по умолчанию
Подобных проблем можно избежать: достаточно оставить один способ считаются закрытыми
работы с классом. Для это в C# в объявлении переменных использует­ поэт ому модификатор
ся ключевое слово p r i v a t e . До этого момента вы встречали только мо­ private зачастую опц~
дификатор public. Поля объектов, помеченные этим модификатором, скается.
были доступны для чтения и редактирования любым другим объектом.
Модификатор private делает поле доступным только изнутри объекта
(или из другого объекта этого же класса).

Статические методы им ею т
доступ к закрытым полям всех