C# 4.0 - řešení praktických programátorských úloh

Page 1

E N C Y K L O P E D I E

Z O N E R

P R E S S

C# 4.0 Ŏešení praktických programátorských úloh

Ben

Watson



C# 4.0 řešení praktických programátorských úloh

Ben Watson


C# 4.0 HOW-TO Ben Watson Authorized translation from the English language edition, entitled C# 4.0 HOW-TO, 1st Edition, 0672330636 by WATSON, BEN, published by Pearson Education, Inc, publishing as Sams Publishing, Copyright © 2010 by Ben Watson. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from Pearson Education, Inc. CZECH language edition published by ZONER SOFTWARE, a.s., Copyright © 2010. Autorizovaný překlad originálního anglického vydání knihy C# 4.0 HOW-TO, vydání první, ISBN 0672330636, autor WATSON, BEN, vydal Pearson Education, Inc, ve vydavatelství Sams Publishing, Copyright © 2010 Ben Watson. Všechna práva vyhrazena. Žádná část této publikace nesmí být reprodukována nebo předávána žádnou formou nebo způsobem, elektronicky ani mechanicky, včetně fotokopií, natáčení ani žádnými jinými systémy pro ukládání bez výslovného svolení Pearson Education, Inc. České vydání vydal ZONER SOFTWARE, a.s., Copyright © 2010.

C# 4.0 – řešení praktických programátorských úloh Autor: Ben Watson Copyright © ZONER software, a.s. Vydání první v roce 2010. Všechna práva vyhrazena. Zoner Press Katalogové číslo: ZR1015 ZONER software, a.s. Nové sady 18, 602 00 Brno Překlad: RNDr. Jan Pokorný Odborný redaktor: Miroslav Kučera Technický redaktor: Hana Fruhwirtová Šéfredaktor: Ing. Pavel Kristián Obálka a fotografie na obálce: Lenka Křížová DTP: Miroslav Kučera

Informace, které jsou v této knize zveřejněny, mohou být chráněny jako patent. Jména produktů byla uvedena bez záruky jejich volného použití. Při tvorbě textů a vyobrazení bylo sice postupováno s maximální péčí, ale přesto nelze zcela vyloučit možnost výskytu chyb. Vydavatelé a autoři nepřebírají právní odpovědnost ani žádnou jinou záruku za použití chybných údajů a z toho vyplývajících důsledků. Všechna práva vyhrazena. Žádná část této publikace nesmí být reprodukována ani distribuována žádným způsobem ani prostředkem, ani reprodukována v databázi či na jiném záznamovém prostředku či v jiném systému bez výslovného svolení vydavatele, s výjimkou zveřejnění krátkých částí textu pro potřeby recenzí. Veškeré dotazy týkající se distribuce směřujte na: Zoner Press ZONER software, a.s Nové sady 18, 602 00 Brno tel.: 532 190 883 e-mail: knihy@zoner.cz www.zonerpress.cz

ISBN 978-80-7413-094-6


3

Stručný obsah Část I – Základy C#

21

Kapitola 1

Základy typů

23

Kapitola 2

Vytváření univerzálních typů

43

Kapitola 3

Obecné zásady psaní kódu

61

Kapitola 4

Výjimky

79

Kapitola 5

Čísla

93

Kapitola 6

Výčty

115

Kapitola 7

Řetězce

125

Kapitola 8

Regulární výrazy

147

Kapitola 9

Generiky

155

Část II – Zpracování dat

169

Kapitola 10

Kolekce

171

Kapitola 11

Soubory a serializace

193

Kapitola 12

Sítě a web

217

Kapitola 13

Databáze

253

Kapitola 14

XML

277

Část III – Interakce s uživatelem

293

Kapitola 15

Delegáti, události a anonymní metody

295

Kapitola 16

Formuláře Windows

309

Kapitola 17

Grafika s formuláři Windows a GDI+

343

Kapitola 18

Windows Presentation Foundation (WPF)

379

Kapitola 19

ASP.NET

417

Kapitola 20

Silverlight

457

Část IV – Pokročilé funkce C#

473

Kapitola 21

LINQ

475

Kapitola 22

Správa paměti

487

Kapitola 23

Vlákna, asynchronní a paralelní programování

505

Kapitola 24

Reflexe a vytváření pluginů

533

Kapitola 25

Aplikační vzory a tipy

543

Kapitola 26

Interakce s operačním systémem a hardwarem

589

Kapitola 27

Ostatní záležitosti

609

Dodatek A

Nepostradatelné nástroje

633


4

Podrobný obsah Úvod

18

Část I – Základy C# Kapitola 1

Základy typů

21 23

Vytvoření třídy

24

Definice členských proměnných, vlastností a metod

25

Definice statických členů

27

Konstruktory

27

Inicializace vlastností při jejich konstrukci

29

Klíčová slova const a readonly

29

Opětovné využívání kódu ve více konstruktorech

30

Odvozování z třídy

31

Volání konstruktoru základní třídy

31

Překrytí metody nebo vlastnosti základní třídy

32

Vytvoření rozhraní

35

Implementace rozhraní

36

Vytvoření struktury

38

Vytvoření anonymního typu

39

Použití abstraktní základní třídy pro zamezení vytváření instancí

40

Rozhraní, nebo abstraktní základní třída?

41

Kapitola 2

Vytváření univerzálních typů

43

Formátování typu s ToString()

44

Jak určit, zda jsou typy shodné?

48

Jak na hašování typů s GetHashCode()?

50

Jak na seřazování typů?

50

Přidělování indexu typům

52

Oznamování klientům, že se něco změnilo

54

Přetěžování operátorů

55

Převod typů na jiné typy

56


5 Jak zabránit dědění

57

Povolení null u hodnotového typu

58

Kapitola 3

Obecné zásady psaní kódu

61

Deklarace proměnných

62

Odložení kontrol typů na dobu běhu (dynamické typy)

63

Dynamické typování pro zjednodušení interoperability s COM

65

Deklarace polí

66

Vytváření vícerozměrných polí

66

Alias jmenného prostoru

67

Podmínkový operátor (:?)

68

Podmínkový operátor (??) zahrnující null

69

Přidávání metod do existujících typů pomocí rozšiřujících metod

70

Volání metod s výchozími parametry

72

Volání metod s pojmenovanými parametry

73

Odložené vytvoření hodnoty až do okamžiku, kdy se na ni odkazuje

73

Vynucení kódových kontraktů

75

Kapitola 4

Výjimky

79

Generování výjimky

80

Zachycení výjimky

80

Zachycení více výjimek

81

Opětovné vygenerování výjimky

82

(Téměř) zaručené vykonání s finally

83

Získávání užitečných informací z výjimek

84

Vytvoření vlastní třídy výjimky

86

Zachycení nezpracovaných výjimek

88

Rady pro používání výjimek

92

Kapitola 5

Čísla

93

Volba mezi Float, Double a Decimal

94

Enormně velká celá čísla (BigInteger)

95

Komplexní čísla

96

Formátování čísel v řetězci

98


6 Převod řetězce na číslo

102

Převody mezi číselnými soustavami

103

Převod čísla na bajty (a naopak)

106

Jak určit, zdali je celé číslo sudé?

107

Jak určit, zdali je celé číslo mocnina dvou?

107

Jak určit, zdali je číslo prvočíslem?

108

Jak určit počet jednotkových bitů?

108

Převod stupňů na radiány

109

Zaokrouhlování čísel

110

Generování více náhodných čísel

112

Generování jedinečných identifikátorů (GUID)

113

Kapitola 6

Výčty

115

Deklarace výčtu

116

Deklarace indikátorů jako výčet

117

Určení, zdali je nastaven konkrétní indikátor

118

Převod výčtu na celé číslo (a naopak)

118

Určení, zda je výčet platný

119

Získání seznamu hodnot výčtu

119

Převod řetězce na výčet

119

Připojování metadat k výčtům pomocí rozšiřujících metod

120

Tipy pro práci s výčty

123

Kapitola 7

Řetězce

125

Převod řetězce na bajty (a naopak)

126

Vytvoření vlastního kódovacího schématu

127

Řádné porovnávání řetězců

131

Změna velikosti písmen

132

Detekce prázdných řetězců

133

Řetězení řetězců: měli byste používat StringBuilder?

133

Řetězení prvků kolekce do řetězce

135

Přidávání znaků pro nový řádek

136

Převod řetězce na pole řetězců

136

Převod binárních dat na řetězec (datový formát Base64)

138


7 Opačné pořadí slov

140

Přirozené seřazení řetězců obsahujících čísla

141

Kapitola 8

Regulární výrazy

147

Vyhledávání textu

148

Extrakce skupin textu

149

Nahrazování textu

149

Shoda a validace

150

Zvyšování výkonu regulárních výrazů

153

Kapitola 9

Generiky

155

Vytvoření generického seznamu

156

Vytvoření generické metody

157

Vytvoření generického rozhraní

158

Vytvoření generické třídy

159

Vytvoření generického delegáta

161

Používání více generických typů najednou

162

Omezování generického typu

162

Převod IEnumerable<Child> na IEnumerable<Parent> (kovariance)

165

Převod IComparer<Child> na IComparer<Parent>(kontravariance)

167

Vytváření entic (dvojice, trojice atd.)

168

Část II – Zpracování dat Kapitola 10

Kolekce

169 171

Výběr správné třídy pro kolekci

172

Inicializace kolekce

174

Iterace přes kolekci nezávisle na její implementaci

174

Vytvoření vlastní kolekce

175

Vytváření vlastních iterátorů pro kolekci

179

Opačné pořadí prvků pole

183

Opačné pořadí prvků propojeného seznamu

183

Získání jedinečných prvků z kolekce

184


8 Četnosti prvků v kolekci

185

Implementace prioritní fronty

186

Vytvoření prefixového stromu (Trie)

189

Kapitola 11

Soubory a serializace

193

Vytváření, čtení a zapisování souborů

194

Odstranění souboru

196

Kombinování proudů (komprimace souboru)

197

Získání velikosti souboru

199

Získání bezpečnostních informací o souboru

199

Kontrola existence souboru a adresáře

201

Seznam jednotek

201

Seznam adresářů a souborů

202

Výběr adresáře procházením

203

Vyhledání souboru nebo adresáře

204

Manipulace s cestami souborů

206

Vytváření jedinečných nebo dočasných názvů souborů

208

Sledování změn souborového systému

208

Získání cest ke složkám Dokumenty, Obrázky atd.

210

Serializace objektů

211

Serializace do proudu v paměti

214

Ukládání dat, když má aplikace omezená oprávnění

214

Kapitola 12

Sítě a web

217

Překlad názvu hostitele do IP adresy

218

Získání názvu hostitele a IP adresy aktuálního stroje

218

Ping na nějaký stroj

219

Získání informací o síťové kartě

220

Vytvoření klienta a serveru TCP/IP

221

Odeslání e-mailu přes SMTP

224

Stahování webového obsahu přes HTTP

225

Nahrání souboru z FTP serveru

229

Odstranění HTML značek z textu

230

Vložení webového prohlížeče do aplikace

231


9 Konzumace RSS kanálu

232

Dynamické generování kanálu RSS v IIS

236

Komunikace mezi procesy na tomtéž stroji (WCF)

238

Komunikace mezi dvěma stroji na téže síti (WCF)

245

Komunikace přes internet (WCF)

247

Odhalování služeb za běhu (WCF)

249

Kapitola 13

Databáze

253

Vytvoření nové databáze ve Visual Studiu

254

Připojení k databázi a získávání dat

256

Vkládání dat do databázové tabulky

261

Odstraňování dat z tabulky

262

Spuštění uložené procedury

263

Transakce

264

Vázání dat k ovládacímu prvku pomocí sady dat

266

Detekce, zda je databázové připojení dostupné

273

Automatické mapování dat na objekty s knihovnou Entity Framework

274

Kapitola 14

XML

277

Serializace objektu do XML a z XML

278

Zápis XML úplně od začátku

282

Čtení XML souboru

284

Validace XML dokumentu

286

Dotazy na XML s XPath

288

Transformace databázových dat do XML

289

Transformace XML do HTML

290

Část III – Interakce s uživatelem Kapitola 15

Delegáti, události a anonymní metody

293 295

Rozhodnutí až při běhu, která metoda se má zavolat

296

Jak se přihlásit k odběru události

298

Publikace události

299


10 Uživatelské rozhraní se musí aktualizovat na jeho vláknu

301

Přiřazení anonymní metody delegátovi

303

Použití anonymní metody jako zpracovatele událostí

304

Jak těžit z výhod kontravariance

306

Kapitola 16

Formuláře Windows

309

Modální a nemodální formuláře

310

Pruh nabídek

311

Dynamické vypínání prvků nabídek

314

Stavový řádek

314

Panel nástrojů

315

Vytvoření rozhraní pro rozdělení okna

316

Dědění formuláře

318

Uživatelský ovládací prvek

322

Časovač

327

Konfigurační hodnoty pro aplikaci a uživatele

328

Efektivní práce s ListView ve virtuálním režimu

331

Vodorovné posouvání nakláněním kolečka myši

333

Vyjímání a vkládání do schránky

337

Obnovení čekacího kurzoru do původní podoby

342

Kapitola 17

Grafika s formuláři Windows a GDI+

343

Definice barev

344

Systémový dialog pro výběr barev

344

Převod barev mezi RGB a HSV

345

Kreslení obrazců

349

Pera

352

Vlastní štětce

354

Transformace

356

Kreslení textu

358

Kreslení textu šikmo

358

Kreslení obrázků

359

Kreslení průhledných obrázků

360

Kreslení do bufferu mimo obrazovku

360


11 Přímý přístup k pixelům bitmapy pro lepší výkon

361

Kreslení s vyhlazováním hran

363

Kreslení bez problikávání

364

Změna velikosti obrázku

365

Vytvoření miniatury obrázku

365

Snímání obsahu obrazovky v prostředí s několika monitory

367

Vzdálenost kurzoru myši od daného bodu

369

Je bod uvnitř daného obdélníka?

370

Je bod uvnitř dané kružnice?

370

Je bod uvnitř dané elipsy?

371

Mají dva obdélníky neprázdný průnik?

372

Tisk a náhled před tiskem

372

Kapitola 18

Windows Presentation Foundation (WPF)

379

Zobrazení okna

380

Volba metody rozvržení

381

Pruh nabídek

381

Stavový řádek

383

Panel nástrojů

383

Standardní příkazy

384

Vlastní příkazy

385

Vypínání a zapínání příkazů

388

Rozbalování a sbalování skupiny ovládacích prvků

389

Reakce na události

390

Oddělení vzhledu od funkcionality

391

Změna stylů při běhu pomocí triggerů

392

Vázání vlastností ovládacího prvku k jinému objektu

393

Formátování hodnot během vázání dat

398

Převod hodnot na jiný typ během vázání dat

398

Vázání ke kolekci

399

Definice způsobu pro zobrazování vázaných dat

400

Definice vzhledu ovládacích prvků pomocí šablon

401

Animace vlastností prvku

402

Realizace trojrozměrné geometrie

403


12 Video na trojrozměrném povrchu

406

Interaktivní ovládací prvky na trojrozměrném povrchu

409

WPF v aplikacích formulářů Windows

413

Formuláře Windows v aplikaci WPF

414

Kapitola 19

ASP.NET

417

Prohlížení ladicích a sledovacích informací

418

Zjištění schopností webového prohlížeče

420

Přesměrování na jinou stránku

421

Formulářová autentizace pro přihlašování uživatelů

423

Jednotný vzhled se vzorovými stránkami

426

Přidání navigačního menu

427

Vázání dat ke GridView

428

Vytvoření uživatelského ovládacího prvku

430

Tvorba flexibilního uživatelského rozhraní s Web Parts

434

Vytvoření jednoduché ajaxové stránky

439

Ověřování platnosti dat

441

Udržování stavu aplikace

445

Udržování stavu uživatelského rozhraní

446

Udržování uživatelských dat v relaci

447

Uložení stavu relace

449

Použití cookies pro obnovení stavu relace

450

ASP.NET Model-View-Controller (MVC)

451

Kapitola 20

Silverlight

457

Vytvoření projektu Silverlightu

458

Přehrávání videa

459

Sestavení ukazatele průběhu pro stahování a přehrávání

463

Reakce na události časovače na vláknu uživatelského rozhraní

465

Obsah v trojrozměrné perspektivě

466

Běh aplikace bez webového prohlížeče

467

Zobrazení výstupu z webové kamery

469

Tisk dokumentu

471


13

Část IV – Pokročilé funkce C# Kapitola 21

LINQ

473 475

Dotaz na objekt kolekce

476

Seřazení výsledků

478

Filtrování kolekce

478

Získání kolekce částí objektů (projekce)

479

Slučování tabulek

479

Dotaz na XML

480

Vytvoření XML

481

Dotazování s Entity Framework

481

Dotaz na webovou službu (LINQ to Bing)

483

Urychlování dotazů s PLINQ (paralelní LINQ)

486

Kapitola 22

Správa paměti

487

Kolik paměti používá aplikace

488

Úklid neřízených prostředků pomocí finalizace

489

Úklid řízených prostředků pomocí vzoru propouštění

491

Vynucený svoz odpadků

496

Vytvoření cache, která umožňuje svoz odpadu

496

Ukazatele

500

Urychlení přístupu k poli

501

Zamezení přesunů paměti

502

Alokace neřízené paměti

503

Kapitola 23

Vlákna, asynchronní a paralelní programování

505

Snadná dělba práce mezi procesory

506

Používání datových struktur ve více vláknech

510

Asynchronní volání metody

510

Fond vláken

512

Vytvoření vlákna

512

Výměna dat s vláknem

513

Ochrana dat používaných ve více vláknech

515


14 Použití metody třídy Interlocked místo zámků

517

Ochrana dat ve více procesech

518

Omezení aplikace na jedinou instanci

520

Omezení počtu vláken, která mohou přistupovat k prostředku

520

Signalizace vláknům událostmi

523

Vícevláknový časovač

526

Zámek typu Reader-Writer

527

Použití asynchronního programovacího modelu

529

Kapitola 24

Reflexe a vytváření pluginů

533

Jmenovitý seznam typů v assembly

534

Přidání vlastního atributu

535

Dynamické vytvoření instance třídy

537

Vyvolání metody na dynamicky vytvořené instanci třídy

537

Implementace pluginové architektury

539

Kapitola 25

Aplikační vzory a tipy

543

Stopky pro potřeby profilace kódu

544

Vyznačování zastaralého kódu

545

Zkombinování událostí do jediné události

546

Implementace vzoru pozorovatel

551

Zprostředkovatel událostí

554

Uložení pozice aplikace na obrazovce

558

Implementace funkce Zpět pomocí objektů příkazů

559

Vzor Model-View-ViewModel ve WPF

567

Lokalizace

577

Lokalizace aplikace formulářů Windows

578

Lokalizace aplikace ASP.NET

579

Lokalizace aplikace WPF

581

Lokalizace aplikace Silverlightu

585

Nasazení aplikace do provozu s ClickOnce

587

Kapitola 26

Interakce s operačním systémem a hardwarem

Verze operačního systému, opravného balíčku a CLR

589 590


15 Informace o CPU a dalším hardwaru

590

Vyžádání oprávnění správce vyvoláním Řízení uživatelských účtů

593

Zapisování do protokolu událostí

595

Přístup k registru

597

Správa služeb Windows

599

Vytvoření služby Windows

599

Volání nativních funkcí Windows pomocí P/Invoke

602

Volání funkcí C v DLL z C#

603

Paměťově mapované soubory

604

Zajištění, aby aplikace pracovala v 32bitovém i 64bitovém prostředí

605

Reakce na změny v konfiguraci systému

606

Využití předností funkcí Windows 7

607

Informace o stavu napájení

608

Kapitola 27

Ostatní záležitosti

609

Okno, které není obdélníkové

610

Ikona pro oznamovací oblast

614

Spořič obrazovky ve WPF

617

Úvodní obrazovka

626

Přehrání zvukového souboru

631

Míchání karet

632

Dodatek A

Nepostradatelné nástroje

633

Reflector

634

NUnit

635

NDepend

638

FXCop

639

Virtual PC

640

Process Explorer a Process Monitor

641

RegexBuddy

642

LINQPad

643

Kde najdete další nástroje

644

Rejstřík

645


16

Věnování Rodičům, Michaelu a Dianně Watsonovým, kteří se mi v mých pubertálních letech přinejmenším dvakrát podvolili, když jsem jim podrobně zdůvodňoval, proč by mi měli koupit software kompilátoru C++, a kteří dělali všechno, co bylo v jejich silách, aby rozvíjeli to, na co jsem měl nadání a co mě zajímalo. Bez jejich vzoru, lásky a rad bych nikdy ničeho nedosáhl. Mé báječné ženě Leticii, která byla nanejvýš trpělivá a laskavá, když jsem se pustil do nového a strastiplného projektu během těch všech ostatních změn v našem životě.

Poděkování Jsem velmi vděčný lidem, kteří sešli ze své cesty proto, aby mi pomohli s touto knihou: Brooku Farlingovi (editor), že mě našel a dal mi tuto příležitost, za veškerou jeho koordinač-

ní práci, trpělivost a tah na branku, aby se podařilo knihu vydat. Marku Strawmayerovi (korektor), že prošel kód a text a zajistil kvalitu toho, co je v knize. Publikačnímu

Sheri Cain.

týmu u Sams, což byl Mark Renfrow, Lori Lyons, Bart Reed, Nonie Ratcliff,


17

O autorovi Ben Watson vyvíjí v .NET od chvíle, kdy bylo vydáno. Než se přidal k Microsoftu, pracoval jako vůdčí vývojář pro firmu GeoEye, kde v .NET vyvinul komunikační systémy pro námořnictvo. Naposled pracoval v týmu Query Pipeline pro Bing, kde pomáhal navrhovat a implementovat masivně škálovatelné distribuované systémy a další interní záležitosti tohoto vyhledávače.

Sdělte nám svůj názor Jako čtenáři této knihy se stáváte těmi nejdůležitějšími kritiky a komentátory. Vážíme si vašeho názoru a chtěli bychom vědět, co děláme správně, co bychom mohli dělat lépe, ve kterých oblastech bychom měli publikovat, a také vaše další podnětné myšlenky, o které jste ochotni se podělit. Jako odborný redaktor Zoner Press vítám vaše názory. Můžete mi psát – poslat e-mail nebo dopis – a sdělit mi, co se vám v této knize líbilo nebo nelíbilo, stejně tak co bychom měli udělat, aby naše další knihy byly lepší. Pokud mi napíšete, nezapomeňte, prosím, připojit název knihy, ISBN, jméno autora, vaše jméno, telefon, fax nebo e-mail. Pozorně zhodnotím vaše názory a poskytnu je všem lidem, kteří pracovali na této knize. Prosím, vězte, že nemohu pomoci s technickými problémy, které se týkají obsahu knihy, a že díky velkému množství e-mailů, jež dostávám, nemohu zaručit odpověď na každou zprávu. E-mail: miroslav.kucera@zoner.cz nebo knihy@zoner.cz. Adresa: Zoner Press ZONER software, a.s. Miroslav Kučera Nové sady 18, 602 00 Brno

Zdrojové soubory Zdrojové soubory k této knize lze stáhnout z následující adresy: http://zonerpress.cz/download/C_4_0_reseni_praktickych_uloh.zip

Velikost souboru ke stažení je cca 31 MB.


18

Úvod Tato kniha přistupuje ke svému tématu hodně odlišně než typické programovací příručky. Tím, že je strukturována do návodů ve formě praktických postupů ve stylu "jak na to", předkládá látku ve scénářích rozložených na kroky, které se snadno reprodukují. V jednotlivých návodech jsem se snažil omezit vysvětlující text na nezbytné minimum, abych se mohl plně soustředit na samotný kód. V kódech nechybí komentáře, které vysvětlují jeho netriviální úseky. Kniha není pouhou strohou učebnicí jazyka či knihovnou. Neprobírají se zde pouze samotné funkce jazyka, uvidíte propracované praktické ukázky aplikačních vzorů, užitečné algoritmy i řadu šikovných tipů, prostě všechno, co můžete využít v mnoha situacích. Vývojáři, jak začínající, tak i pokročilí, najdou v této knize stovky užitečných témat. Ať už je to sekce o méně známých operátorech C#, nebo jak seřazovat řetězce obsahující čísla, nebo jak implementovat funkci Zpět (Undo), kniha prostě obsahuje hotová řešení, která jsou užitečná v mnoha rozličných situacích, bez ohledu na to, jakou úrovní dovedností je vývojář vybaven. Zkrátka, je to ten druh knihy, který jsem chtěl mít na svém stole neustále po ruce, když jsem se poprvé učil programovat a zároveň jazyk C#, vždy, když jsem si něco potřeboval rychle ověřit nebo si připomenout, jak se dělá to či ono.

Jak z knihy vytěžit co nejvíc Tuto knihu jsem navrhl tak, aby se snadno četla po jednotlivých tématech. Mým cílem je, abyste plně porozuměli jazyku C# 4.0. Předmět výkladu je rozdělen do čtyř částí, které jsou složeny z kapitol, v nichž se snadno orientuje a snadno se s nimi pracuje. Část I, "Základy C#", se věnuje běžné funkcionalitě C#, kterou budete využívat pokaždé, bez ohledu na to, co budete programovat. Ačkoliv se někomu může zdát jako příliš elementární, obsahuje spoustu užitečných rad, takže budete schopni vytěžit maximum i ze základních témat. Kapitola 1 – Základy typů Kapitola 2 – Vytváření univerzálních typů Kapitola 3 – Obecné zásady psaní kódu Kapitola 4 – Výjimky Kapitola 5 – Čísla Kapitola 6 – Výčty Kapitola 7 – Řetězce Kapitola 8 – Regulární výrazy Kapitola 9 – Generiky


19 V části II, "Zpracování dat", detailně prodiskutujeme problematiku ukládání dat a manipulace s nimi (včetně práce s daty umístěnými někde na internetu). Kapitola 10 – Kolekce Kapitola 11 – Soubory a serializace Kapitola 12 – Sítě a web Kapitola 13 – Databáze Kapitola 14 – XML

V části III, "Interakce s uživatelem", se probírají nejoblíbenější paradigmata uživatelského rozhraní v .NET, ať už pracujete na své ploše, na webech, nebo děláte obojí. Kapitola 15 – Delegáti, události a anonymní metody Kapitola 16 – Formuláře Windows Kapitola 17 – Grafika s formuláři Windows a GDI+ Kapitola 18 – Windows Presentation Foundation (WPF) Kapitola 19 – ASP.NET Kapitola 20 – Silverlight

V části IV, "Pokročilé funkce C#", se probírají pokročilejší témata. Jedná se o látku, s jejíž pomocí dostanete své aplikace na kvalitativně vyšší úroveň, pokud jde o výkon, návrhové vzory, užitečné algoritmy a další aspekty. Kapitola 21 – LINQ Kapitola 22 – Správa paměti Kapitola 23 – Vlákna, asynchronní a paralelní programování Kapitola 24 – Reflexe a vytváření pluginů Kapitola 25 – Aplikační vzory a tipy Kapitola 26 – Interakce s operačním systémem a s hardwarem Kapitola 27 – Ostatní záležitosti Dodatek A – Nepostradatelné nástroje

Veškerý kód jsme naprogramovali ve Visual Studiu 2010, v mnoha případech ovšem vystačíte i s dřívějšími verzemi, zejména jedná-li se o kód, který nepožaduje .NET 4. Nemáte-li Visual Studio, můžete si ze stránek www.microsoft.com/express/default.aspx stáhnout verzi Express. S touto verzí budete schopni sestavit prakticky všechny ukázky kódu uvedené v této knize.


20

Jak dále rozvíjet své vědomosti Žádná samostatná kniha nemůže plně pokrýt C# a .NET Framework. Dokonce ani nemůže doufat, že se jí podaří vyčerpávajícím způsobem probrat nějaké dílčí téma z tohoto světa. A i kdyby taková kniha existovala, patrně byste ji vůbec neunesli a celý svůj život strávili její četbou. Jakmile však zvládnete základy, existuje spousta zdrojů, v nichž můžete najít odpovědi na své další otázky, a hlouběji se ponořit do .NET. MSDN dokumentace pro .NET, která je umístěna na http://msdn.microsoft.com/en-us/ aa139615.aspx, je naprosto prvotřídní. U většiny témat najdete nejenom ukázky kódu, ale i vysvětlení toho, jak se používají. Jako bonus navíc má kdokoliv možnost přidat na konec každého tématu užitečný obsah. Najde se tam spousta dobrých tipů od ostatních vývojářů .NET. Vývojářská fóra .NET, viz adresa http://social.msdn.microsoft.com/Forums/en-US/category/netdevelopment, jsou vynikajícím místem, kde můžete získat odpovědi na své otázky od expertů, z nichž mnozí se podíleli na vývoji a testování .NET. Zjistil jsem také, že dobrým místem pro otázky je web StackOverflow.com. Nejlepší rada, kterou vám ohledně rozvíjení vašich vědomostí mohu dát, je ta, abyste prostě psali software. Vydržte u toho, přemýšlejte o nových projektech, používejte nové technologie, snažte se překračovat své momentální schopnosti. Tato i jiné knihy jsou velmi užitečné, ale pochopitelně jen do jisté hranice. Pak už nezbude nic jiného, než abyste do toho skočili po hlavě a začali psát kód. Při této činnosti vám kniha vždy poslouží jako spolehlivá referenční příručka, nebudete-li náhodou vědět, jak se pustit do nějakého tématu. Mnoho štěstí při kódování!


21

ČÁST I Základy C# Obsah této části: Kapitola 1

Základy typů

Kapitola 2

Vytváření univerzálních typů

Kapitola 3

Obecné zásady psaní kódu

Kapitola 4

Výjimky

Kapitola 5

Čísla

Kapitola 6

Výčty

Kapitola 7

Řetězce

Kapitola 8

Regulární výrazy

Kapitola 9

Generiky



23

KAPITOLA 1 Základy typů Obsah této kapitoly:  Vytvoření třídy  Definice členských proměnných, vlastností a metod  Definice statických členů  Konstruktory  Inicializace vlastností při jejich konstrukci  Klíčová slova const a readonly Opětovné využívání kódu ve více konstruktorech  Odvozování z třídy  Volání konstruktoru základní třídy  Překrytí metody nebo vlastnosti základní třídy  Vytvoření rozhraní  Implementace rozhraní  Vytvoření struktury  Vytvoření anonymního typu  Použití abstraktní základní třídy pro zamezení vytváření instancí  Rozhraní, nebo abstraktní základní třída?


24

Kapitola 1 – Základy typů

V této kapitole si vysvětlíme základy, jak vytvářet typy v C#. Jestliže už něco o C# víte, poslouží většina kapitoly jako rekapitulace. Poté, co probereme členy třídy, mezi něž patří členské proměnné, vlastnosti a metody, dozvíte se něco více o konstruktorech a vytváření (a implementaci) rozhraní. Také se dozvíte, kdy se mají používat struktury. Ačkoliv informace obsažené v této kapitole jsou základní, lze je označit za důležité. Podobně jako u mnoha jiných věcí i zde platí, že pokud nemáte v malíčku základy, nikdy nic neuděláte pořádně.

Vytvoření třídy Scénář/problém. Potřebujete vytvořit deklaraci nějaké třídy.

Řešení. Začněme něčím jednoduchým. Deklarujme třídu, která bude obsahovat souřadnice bodu v trojrozměrném prostoru. // Výchozí jmenné prostory, které se mají importovat, // Visual Studio je zařadí do každého souboru using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ClassSample { // Veřejná, takže bude viditelná vně assembly public class Vertex3d { } }

Třída, kterou jsme nadefinovali, je prozatím prázdná, ale v této kapitole ji postupně naplníme. Třída je definovaná jako veřejná (public), což znamená, že je viditelná pro jakýkoliv další typ, který se odkazuje na její assembly. Programovací jazyk C# definuje několik modifikátorů přístupu, které jsou podrobně uvedeny v tabulce 1.1. Tabulka 1.1. Modifikátory přístupu. Přístup

Aplikovatelné na

Popis

Veřejný (public)

Typy, členy

Přístupné všem, dokonce i vně assembly

Privátní (private)

Typy, členy

Přístupné kódu v tomtéž typu

Interní (internal)

Typy, členy

Přístupné kódu v tomtéž assembly


C# 4.0 – řešení praktických programátorských úloh

25

Přístup

Aplikovatelné na

Popis

Chráněný (protected)

Členy

Přístupné kódu v tomtéž typu nebo odvozeném typu

Chráněný interní (protected internal)

Členy

Přístupné kódu v tomtéž assembly nebo odvozené třídě v jiném assembly

Jestliže třída nespecifikuje svou přístupnost, výchozí je internal.

Definice členských proměnných, vlastností a metod Scénář/problém. Potřebujete do definice třídy přidat členské proměnné, vlastnosti a metody.

Řešení. Přidejte základní prvky třídy Vertex3d, aby mohla být k něčemu užitečná. public class Vertex3d { // Členské proměnné (fields) private double _x; private double _y; private double _z; // Vlastnosti public double X { get { return _x; } set { _x = value; } } public double Y { get { return _y; } set { _y = value; } } public double Z { get { return _z; } set { _z = value; } } // Metoda public void SetToOrigin() { X = Y = Z = 0.0;


Kapitola 1 – Základy typů

26 } }

Pár poznámek k předchozímu kódu: Všechny

členské proměnné jsou deklarovány jako privátní (private), což se obecně dopo-

ručuje. Ačkoli vlastnosti jsou deklarovány jako veřejné (public), mohou být také privátní (priva-

te), chráněné (protected) nebo chráněné interní (protected internal), jak si přejete. Vlastnosti mohou mít get, set, nebo obojí. Ve vlastnostech je value implicitní argument (neboli předpokládaný v kódu).

V následujícím příkladu by se do X předala hodnota 13.0 v argumentu value. Vertex3d v = new Vertex3d(); v.X = 13.0;

Automaticky implementované vlastnosti Často uvidíte kód tohoto druhu: class MyClass { private int _field = 0; public int Field { get { return _field; } { set { _field = value; } } }

Pro něj má C# zkrácený zápis: class MyClass { public int Field { get; set; } // Hodnota se nyní musí inicializovat v konstruktoru public MyClass() { this.Field = 0; } }

Poznámka. Nemůžete mít automaticky implementovanou vlastnost, která by měla pouze get (pokud byste neměli žádnou podpůrnou členskou proměnnou, jakým způsobem byste nastavili vlastnost?), nicméně může mít privátní set: public int Field { get; private set; }


C# 4.0 – řešení praktických programátorských úloh

27

Definice statických členů Scénář/problém. Potřebujete definovat data nebo metody, které se aplikují na typ, nikoliv na jednotlivé instance. Často se také využívají u metod, které operují na více instancích daného typu.

Řešení. Přidejte klíčové slovo static, viz následující metoda, která sčítá dva objekty typu Vertex3d. public class Vertex3d { ... public static Vertex3d Add(Vertex3d a, Vertex3d b) { Vertex3d result = new Vertex3d(); result.X = a.X + b.X; result.Y= a.Y + b.Y; result.Z = a.Z + b.Z; return result; } }

Statická metoda se volá takto: Vertex3d a = new Vertex3d(0,0,1); Vertex3d b = new Vertex3d(1,0,1); Vertex3d sum = Vertex3d.Add(a,b);

Konstruktory Scénář/problém. Potřebujete automaticky inicializovat nové objekty třídy.

Řešení. Definujte speciální metodu, které se říká konstruktor. Má stejný název jako třída a nemá žádný návratový typ. Konstruktor se spustí poté, co se vytvořil typ; nikdy se nevolá přímo. Podívejte se nyní na dva konstruktory pro třídu Vertex3d – jeden přebírá argumenty, druhý provádí jistou výchozí inicializaci. class Vertex3d { public Vertex3d()


Kapitola 1 – Základy typů

28 {

_x = _y = _z = 0.0; } public Vertex3d(double x, double y, double z) { this._x = x; this._y = y; this._z = z; } }

Poznámka. Konstruktory nemusejí být veřejné. Například můžete označit konstruktor jako chráněný (protected), čímž bude přístupný pouze z odvozených tříd. Dokonce můžete mít privátní konstruktor, aby se zabránilo vytváření instancí (u pomocných tříd), nebo aby byl přístupný pouze z jiných metod téže třídy (patrně půjde o statické tovární metody).

Statický konstruktor a inicializace Scénář/problém. Třída má statická data, která je potřeba inicializovat.

Řešení. Statické členské proměnné se dají inicializovat dvěma způsoby. Prvním způsobem je statický konstruktor, což je obdoba standardního konstruktoru, ovšem s tím rozdílem, že nemá modifikátory přístupu a ani argumenty: public class Vertex3d { private static int _numInstances; static Vertex3d() { _numInstances = 0; } ... }

Kvůli lepšímu výkonu se ovšem dává vždy, kdykoliv je to možné, přednost inicializaci statických členských proměnných, jak to vidíte zde: public class Vertex3d { private static int _numInstances = 0; }


217

KAPITOLA 12 Sítě a web Obsah této kapitoly:  Překlad názvu hostitele do IP adresy  Získání názvu hostitele a IP adresy aktuálního stroje  Ping na nějaký stroj  Získání informací o síťové kartě  Vytvoření klienta a serveru TCP/IP  Odeslání e-mailu přes SMTP  Stahování webového obsahu přes HTTP  Nahrání souboru z FTP serveru  Odstranění HTML značek z textu  Vložení webového prohlížeče do aplikace  Konzumace RSS kanálu  Dynamické generování kanálu RSS v IIS  Komunikace mezi procesy na tomtéž stroji (WCF)  Komunikace mezi dvěma stroji na téže síti (WCF)  Komunikace přes internet (WCF)  Odhalování služeb za běhu (WCF)


218

Kapitola 12 – Sítě a web

Jen výjimečně dnes najdeme aplikaci, která nemá žádnou funkcionalitu spojenou s internetem. Softwarový svět je stále více a více propojený a u většiny softwaru se očekává, že bude mít nějakou síťovou funkcionalitu, i kdyby to mělo být jen něco tak triviálního, jako je kontrola aktualizací. Ačkoliv k dobrým řešením síťových úloh vede trnitá cesta, tato kapitola vás posune o hezký kus dopředu. Předvedu vám několik úloh, z nichž několik lze označit za vysloveně základní.

Překlad názvu hostitele do IP adresy Scénář/problém. Potřebujete přeložit název hostitele, jako je microsoft.com, do jeho IP adres.

Řešení. Hodně funkcionality, se kterou se setkáte v této dvanácté kapitole, obsahuje jmenný prostor System.Net (včetně tak základních věcí, jako jsou třídy IPAddress a Dns). string host = "www.microsoft.com"; // Připomínám, že hostitel může mít více IP adres IPAddress[] addresses = Dns.GetHostAddresses(host); foreach (IPAddress addr in addresses) { Console.Write("\t{0}", addr); }

Podívejte se na výstup z ukázkového běhu pro několik běžných hostitelských názvů: www.microsoft.com 207.46.19.254 207.46.19.190 www.live.com 204.2.160.40 204.2.160.49 www.google.com 208.67.219.230 208.67.219.231 www.yahoo.com 209.131.36.158

Získání názvu hostitele a IP adresy aktuálního stroje Scénář/problém. Chcete získat hostitelský název a IP adresy aktuálního stroje.

Řešení. K řešení z předchozí sekce stačí přidat volání, kterým získáte název aktuálního hostitele.


C# 4.0 – řešení praktických programátorských úloh

219

string hostname = Dns.GetHostName(); Console.WriteLine("Název hostitele: {0}", hostname); IPAddress[] addresses = Dns.GetHostAddresses(hostname); foreach (IPAddress addr in addresses) { Console.WriteLine("IP adresa: {0} ({1})", addr.ToString(), addr.AddressFamily); }

A takhle vypadá výstup na mém stroji. Povšimněte si v seznamu IPv6 adres: Název hostitele: Ben-Desktop IP adresa: fe80::2c4c:372:e7ee:35b7%14 (InterNetworkV6) IP adresa: fe80::c1aa:9268:a7f0:a203%8 (InterNetworkV6) IP adresa: 192.168.1.2 (InterNetwork) IP adresa: 2001:0:4137:9e50:2c4c:372:e7ee:35b7 (InterNetworkV6)

Ping na nějaký stroj Scénář/problém. Potřebujete detekovat, zdali jsou síť nebo hostitel dostupní.

Řešení. .NET obsahuje rozhraní, které umožňuje udělat tzv. ping. Toto rozhraní podporuje synchronní a asynchronní operace: System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping(); System.Net.NetworkInformation.PingReply reply = ping.Send("yahoo.com"); Console.WriteLine("adresa: {0}", reply.Address); Console.WriteLine("volby: don’t fragment: {0}, TTL: {1}", reply.Options.DontFragment, reply.Options.Ttl); Console.WriteLine("cesta tam a zpět: {0}ms", reply.RoundtripTime); Console.WriteLine("stav: {0}", reply.Status);

Poznámka. Mnohé sítě jsou nakonfigurovány tak, že nepovolují ping vně svých lokálních sítí. Při používání této funkcionality tak musíte zachytávat PingException a prohlížet vnitřní výjimky, abyste se dozvěděli konkrétní příčinu nezdaru. Když se podíváte do dokumentace MSDN na metodu Send(), naleznete další možné druhy výjimek.


220

Kapitola 12 – Sítě a web

Výstup vypadá takto: adresa: 69.147.114.224 volby: don’t fragment: False, TTL: 49 cesta tam a zpět: 111ms stav: Success

Získání informací o síťové kartě Scénář/problém. Chcete získat nízkoúrovňové informace o všech síťových adaptérech v počítači.

Řešení. Tuto funkčnost nabízí třída System.Net.NetworkInformation.NetworkInterface. NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces(); foreach (NetworkInterface nic in nics) { // V zásadě jde jen o to, dotázat se na houf vlastností Console.WriteLine("ID: {0}", nic.Id); Console.WriteLine("Název: {0}", nic.Name); Console.WriteLine("Fyzická adresa: {0}", nic.GetPhysicalAddress()); IPInterfaceProperties props = nic.GetIPProperties(); PrintIPCollection("DHCP Servery: ", props.DhcpServerAddresses); }

Kompletní kód najdete v projektu NicInfo ve zdrojových kódech pro tuto kapitolu. A takto vypadá výstup pro jeden adaptér: ID: {6B124BB0-CFBE-4DA8-831E-3FD323733CD4} Název: Local Area Connection Popis: Marvell Yukon 88E8053 PCI-E Gigabit Ethernet Controller Typ: Ethernet Stav: Up Rychlost: 100000000 Podporuje Multicast: True Jen přijímat: False Fyzická adresa: 000129A4C39B DHCP Servery: DNS Servery: 208.67.222.222 208.67.220.220


C# 4.0 – řešení praktických programátorských úloh

221

Vytvoření klienta a serveru TCP/IP Scénář/problém. Jste v situaci, kdy existující přenosový protokol nevyhovuje vašim potřebám. Pro vysvětlení – protokol HTTP může být příliš zjednodušující, SOAP příliš těžký a RPC příliš složitý. Také nemůžete použít ani WCF (Windows Communication Foundation). V takové situaci budete muset navrhnout svůj vlastní protokol aplikační úrovně, který bude postaven na TCP/IP.

Řešení. V .NET se klient i server TCP/IP vytvoří velmi lehce. Pusťme se nejprve do vytvoření serveru, viz výpis 12.1. Jeho logika je snadná na pochopení: Spustíme cyklus. V něm čekáme na nějaké připojení. Jakmile se připojení uskuteční, vytvoříme vlákno, abychom je mohli zpracovat. Získáme zprávu. Odešleme odpověď. Uzavřeme připojení a vrátíme se z vlákna.

Výpis 12.1. TCP server. using System; using System.Net.Sockets; using System.Net; using System.Text; using System.Threading; namespace TcpServer { class Program { static void Main(string[] args) { IPAddress localhost = IPAddress.Parse("127.0.0.1"); TcpListener listener = new System.Net.Sockets.TcpListener(localhost, 1330); listener.Start(); while (true) { Console.WriteLine("Čekáme na připojení"); // AcceptTcpClient čeká na nějaké připojení z klienta TcpClient client = listener.AcceptTcpClient(); // Nastartujeme nové vlákno, abychom mohli zpracovat toto připojení, // takže můžeme jít zpět a čekat na dalšího klienta


Kapitola 12 – Sítě a web

222

Thread thread = new Thread( new ParameterizedThreadStart(HandleClientThread)); thread.Start(client); } } static void HandleClientThread(object obj) { TcpClient client = obj as TcpClient; bool done = false; while (!done) { string received = ReadMessage(client); Console.WriteLine("Přijato: {0}", received); done = received.Equals("bye"); if (done) SendResponse(client, "BYE"); else SendResponse(client, "OK"); } client.Close(); Console.WriteLine("Připojení uzavřeno"); } private static string ReadMessage(TcpClient client) { byte[] buffer = new byte[256]; int totalRead = 0; // Čte bajty, dokud proud neindikuje, že další nejsou do { int read = client.GetStream().Read(buffer, totalRead, buffer.Length - totalRead); totalRead += read; } while (client.GetStream().DataAvailable); return Encoding.Unicode.GetString(buffer, 0, totalRead); } private static void SendResponse(TcpClient client, string message) { // Zajistěte, aby se na druhém konci dekódovalo se stejným formátem! byte[] bytes = Encoding.Unicode.GetBytes(message); client.GetStream().Write(bytes, 0, bytes.Length); } } }


C# 4.0 – řešení praktických programátorských úloh

223

Jediný způsob, jak se dá zastavit běh tohoto serveru, je použít klávesovou zkratku Ctrl+C (což je v podstatě standard pro konzolové servery). Nyní se pustíme do klienta, viz výpis 12.2. Jeho logika je neméně průzračná: Připojíme se k serveru. Běháme v cyklu, dokud nedostaneme signál, že máme skončit. Odešleme zprávu. Přečteme odpověď. Je-li odpověď "BYE", signalizuje to konec.

Výpis 12.2. TCP klient. using System; using System.Text; using System.Net; using System.Net.Sockets; namespace TcpClientTest { class Program { static void Main(string[] args) { TcpClient client = new TcpClient("127.0.0.1", 1330); bool done = false; Console.WriteLine("Napište ‘bye’, chcete-li připojení ukončit"); while (!done) { Console.Write("Zadejte zprávu, která se má odeslat na server: "); string message = Console.ReadLine(); SendMessage(client, message); string response = ReadResponse(client); Console.WriteLine("Odpověď: " + response); done = response.Equals("BYE"); } } private static void SendMessage(TcpClient client,string message) { // Zajistěte, aby se na druhém konci kódovalo se stejným formátem! byte[] bytes = Encoding.Unicode.GetBytes(message); client.GetStream().Write(bytes, 0, bytes.Length); }


Ben Watson

C# 4.0 řešení praktických programátorských úloh ZONER software, a.s. významný producent softwaru v oblasti digitální fotogra¿e, poþítaþové gra¿ky a multimédií, poskytovatel internetových služeb, souvisejících s prezentací na internetu a e-komercí, a nakladatelství odborné literatury.

Sháníte rychlá, robustní a efektivní programovací řešení pro Microsoft C# 4.0? Pak je tato kniha přesně to, co hledáte. Najdete v ní přes 200 hotových řešení, nejlepší praktiky či vyzkoušené ukázky kódu pro všechno možné (od tříd po výjimky, od sítí po XML, od LINQ po Silverlight). Kniha zahrnuje hlavní rozšíření jazyka, která byla představena v C# 4.0 a .NET 4.0. Pokud trpíte chronickým nedostatkem času, na nic nečekejte a začněte rovnou zde. Získejte hned teď odpovědi, jimž můžete důvěřovat, a kód, který můžete hned používat. Témata popisovaná v knize: • • • • • • • • • • • • •

Základy typů Vytváření univerzálních typů Obecné zásady psaní kódu Výjimky Čísla Výčty Řetězce Regulární výrazy Generiky Kolekce Soubory a serializace Sítě a web Databáze

• • • • • • • • • • • • •

XML Delegáti, události a anonymní metody Formuláře Windows Grafika s formuláři Windows a GDI+ Windows Presentation Foundation (WPF) ASP.NET Silverlight LINQ Správa paměti Vlákna, asynchronní a paralelní programování Reflexe a vytváření pluginů Aplikační vzory a tipy Interakce s operačním systémem a hardwarem

O autorovi Ben Watson je softwarový inženýr z týmu Bing společnosti Microsoft. Pomáhá navrhovat a implementovat masivně škálovatelné distribuované systémy a další interní záležitosti pro vyhledávač Bing. Než se přidal k Microsoftu, pracoval jako vůdčí vývojář pro GeoEye, což je hlavní poskytovatel satelitního zobrazování. Bloguje na PhilosophicalGeek.com, kde zveřejnil spoustu populárních návodů pro psaní kódu v C# a C++. Zdrojové soubory ke knize zonerpress.cz/download/C_4_0_reseni_praktickych_uloh.zip

Z O N E R

www.zoner.cz

P R E S S

Pod tímto logem vycházejí publikace určené pro každého vážného zájemce o práci s počítačem. Od ryze praktických příruček a průvodců až po komplexní publikace o všem, co potřebuje grafik, webdesignér, vývojář či programátor při každodenní práci. Na slevy, které můžete získat, a vydavatelský plán, v němž vedle knih domácích odborníků najdete celou řadu titulů světově uznávaných autorů, se informujte na adrese vydavatelství.

© Foto: Lenka Křížová

E N C Y K L O P E D I E

DOPORUČENÁ CENA: 539 kč KATALOGOVÉ ČÍSLO: ZR1015

Zoner Press tel.: 532 190 883 e-mail: knihy@zoner.cz www.zonerpress.cz ZONER software, a.s., Nové sady 18, 602 00 Brno

ISBN 978-80-7413-094-6

9 7 8 8 0 7 4 1 3 0 9 4 6


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.