Lekce 1 - Úvod do C# a .NET Frameworku
Vítejte u první lekce populárního C#.NET kurzu, který vám odhalí jazyk C# i framework .NET. Budeme se učit postupně, od úplných začátků až po složité konstrukce, objektové modely a např. práci s databází nebo webové aplikace. S trochou trpělivosti a vytrvalosti se tak z tebe stane dobrý programátor.
Abychom plně porozuměli jazyku C#, ohlédněme se do minulosti na to, jak se programovací jazyky vyvíjely. Bude pro nás totiž důležité pochopit, jak C# pracuje a proč je dobré programovat právě v něm.
Vývoj programovacích jazyků
1. generace jazyků – Strojový kód
Procesor počítače umí vykonávat jen omezené množství jednoduchých instrukcí, které jsou uloženy jako sekvence bitů, jsou to tedy čísla. Ta se mu obvykle zadávají v hexadecimální (šestnáctkové) soustavě. Instrukce jsou tak elementární, že umožňují pouze např. sčítání adres nebo skoky mezi instrukcemi. Nelze např. jednoduše sečíst dvě čísla, musíme se na čísla dívat jako na adresy v paměti a takové sečtení čísel zabere několik instrukcí. Program sčítající dvě čísla by vypadal např. takto:
2104 1105 3106 7001 0053 FFFE 0000
Instrukce se procesoru předloží v binární podobě. Takovýto kód je samozřejmě extrémně nečitelný a závisí na instrukční sadě daného CPU. V tomto jazyce určitě nebude jednoduché tvořit nějaké programy, bohužel každý program musí být nakonec do tohoto jazyka přeložen, aby mohl být na procesoru počítače spuštěn.
2. generace jazyků – Assembler
Assembler (zkráceně ASM) není o nic jednodušší než strojový kód, ale je lidsky čitelný. Jedná se o strojový kód, ve kterém mají instrukce slovní označení (kód), člověk si tedy nemusí pamatovat čísla. Kódy instrukcí se poté přeloží do výše uvedeného strojového kódu. Stejný program by v ASM vypadal takto:
ORG 100 LDA A ADD B STA C HLT DEC 83 DEC –2 DEC 0 END
Vidíme, že podoba je poněkud lidštější, ale nezasvěcení lidé stále vůbec netuší, jak program funguje (včetně mne).
3. generace jazyků
Jazyky ve třetí generaci konečně nabízejí uživateli určitou abstrakci toho, jak program vidí počítač, a zaměřují se na to, jak program vidí člověk. Naše čísla jsou vnímána již jako proměnné, zdrojový kód připomíná matematický zápis.
Sečtení dvou čísel by v jazyce C vypadalo takto:
int main(void) { int a, b, c; a = 83; b = -2; c = a + b; return 0; }
Všichni asi tušíme, co program dělá: sečte čísla 83
a
-2
a výsledek uloží do proměnné c
. U všech
jazyků třetí generace je samozřejmě výhodou vysoká čitelnost. S dalším
vývojem šly jazyky ještě dál a přinesly objektově
orientované programování, ale o tom až později. Jazyky ve třetí
generaci spadají v zásadě do tří kategorií:
1. Kompilované jazyky
Kompilované (neřízené) jazyky mají tedy svůj zdrojový kód v jazyce, kterému lidé dobře rozumí. Tento zdrojový kód se samozřejmě musí přeložit do strojového kódu, aby ho bylo možné spustit na procesoru. Tento překlad zajišťuje překladač (kompiler), který přeloží najednou celý program do strojového kódu.
Kompilace má tyto výhody:
- Rychlost – Jediné zbrzdění spočívá v jednorázové kompilaci, přeložený program poté běží srovnatelně rychle, jako kdyby byl napsán např. v ASM.
- Nepřístupnost zdroj. kódu – Program se šíří již zkompilovaný, není jej tedy možné jednoduše modifikovat, pokud zároveň nevlastníte jeho zdroj. kód.
- Snadné odhalení chyb ve zdroj. kódu – Pokud zdrojový kód obsahuje chybu, celý proces kompilace spadne a programátor je s chybou seznámen. To značně zjednodušuje vývoj.
Dále jsou tu samozřejmě i nevýhody:
- Závislost na platformě – Program je stále závislý na platformě, tedy na typu procesoru a operačním systému. Zkompilovaný program nemůžeme vzít a přenést na jinou platformu, aniž ho na této nové platformě zkompilujeme.
- Nemožnost editace – Jakmile se program jednou zkompiluje do strojového kódu, nelze ho editovat jinak než opětovnou kompilací. To pochopitelně platí i pro výše zmíněné jazyky.
- Memory management – Vzhledem k tomu, že počítač danému programu nerozumí a jen mechanicky vykonává instrukce, můžeme se někdy setkat s velmi nepříjemnými chybami s přetečením paměti. Kompilované jazyky obvykle nemají automatickou správu paměti a jsou to jazyky nižší (s nižším komfortem pro programátora). Běhové chyby způsobené zejména špatnou správou paměti se kompilací neodhalí.
Příkladem kompilovaných jazyků jsou např. jazyk C, jeho objektový následník C++ nebo Pascal / Delphi.
2. Interpretované jazyky
Interpretace se snaží řešit problém přenositelnosti programů mezi různými platformami a také přichází s vyšším komfortem pro programátora. Interpret funguje podobně jako kompiler, jen nepřekládá program celý najednou, ale pouze to, co je v danou chvíli potřeba. (Interpreter znamená v angličtině tlumočník, nejprve tedy vyslechne jednu větu mluvčího a tu poté přeloží a vysloví. Překlad probíhá během proslovu, tedy běhu programu, po větách/instrukcích. Kompiler/překladač přeloží rozhovor celý najednou a poté ho celý přečte.) Můžeme si představit, že výše uvedený zdrojový kód by interpret četl po jednotlivých řádcích, tu část by vždy zkompiloval do strojového kódu a vykonal. Výsledek kompilace by zahodil a přesunul by se na další řádek. Možná vám to připadá jako plýtvání výkonem procesoru a je pravda, že tento způsob běhu programu také není zrovna nejrychlejší.
Jaké může mít tedy tento postup výhody? Je jich hned několik:
- Přenositelnost – Program je plně přenositelný, existuje-li tedy interpret pro danou platformu, půjde na ní zdrojový kód programu spustit (a vývoj interpretu je snazší než vývoj kompilátoru).
- Jednodušší vývoj – Ve vyšších jazycích jsme odstíněni od správy paměti, kterou za nás dělá tzv. garbage collector (dále v seriálu si o něm řekneme více). Často také nemusíme ani zadávat datové typy a máme k dispozici vysoce komfortní kolekce a další struktury.
- Stabilita – Díky tomu, že interpret kódu rozumí, předejde chybám, které by zkompilovaný program jinak klidně vykonal. Běh interpretovaných programů je tedy určitě bezpečnější. Dále umožňuje zajímavou vlastnost, tzv. reflexi, kdy program za běhu zkoumá sám sebe, ale o tom později.
- Jednoduchá editace – Program můžeme vyvíjet po částech a nahrávat na cílové umístění. Díky tomu, že se nemusí kompilovat, ho je možné jednoduše editovat "za běhu".
Interpret má tři zásadní nevýhody:
- Rychlost – Interpretace může být mnohdy velmi pomalá a program tak plně nevyužívá výkon počítače.
- Často obtížné hledání chyb – Kvůli kompilaci za běhu se chyby v kódu objeví až ve chvíli, kdy je kód spuštěn. To může být někdy velmi nepříjemné.
- Zranitelnost – Protože se program šíří v podobě zdrojového kódu, každý do něj může zasahovat nebo krást jeho části.
Příkladem interpretovaného jazyka je např. PHP. Na většině webů tento poměrně pohodlný jazyk výkonově stačí, ale například Facebook používá speciální kompilovanou verzi PHP, zájemci se mohou podívat na projekt HipHop for PHP.
3. Jazyky s virtuálním strojem
Napadlo vás, co by se stalo, kdyby se oba dva výše zmíněné způsoby spojily? Pokud ano, gratuluji, vynalezli jste virtuální stroj. Jedná se o nejmodernější podobu jazyka, která je v současné době také nejrozšířenější a nejlepší volbou pro vývoj většiny aplikací. Nebudu vám tajit, že do této kategorie spadá samotný C# nebo Java.
Zdrojový kód je nejprve přeložen do tzv. mezikódu, kterému Microsoft říká CIL (Common Intermediate Language). Jedná se v podstatě o strojový (binární) kód, který má ale o poznání jednodušší instrukční sadu a přímo podporuje objektové programování. Tento mezikód je potom díky jednoduchosti relativně rychle interpretovatelný tzv. virtuálním strojem (tedy interpretem, v případě .NET je to tzv. CLR – Common Language Runtime). Výsledkem je strojový kód pro náš procesor.
Určitě jste trochu vyděšení, ale věřte, že jsme v podstatě odstranili nevýhody interpretu i kompileru a můžeme využívat mnohé z jejich výhod:
- Odhalení chyb ve zdrojovém kódu – Díky kompilaci do CIL jednoduše odhalíme chyby ve zdrojovém kódu.
- Stabilita – Díky tomu, že interpret kódu rozumí, zastaví nás před vykonáním nebezpečné operace a na chybu upozorní. Můžeme také provádět reflexi (i když pro CIL, ale od toho jsme většinou odstíněni).
- Jednoduchý vývoj – Máme k dispozici hi-tech datové struktury a knihovny, správu paměti za nás provádí garbage collector.
- Slušná rychlost – Rychlost se u virtuálního stroje pohybuje mezi interpretem a kompilerem. Virtuální stroj již výsledky své práce po použití nezahazuje, ale dokáže je cachovat, sám se tedy optimalizuje při četnějších výpočtech a může dosahovat až rychlosti kompileru (Just-In-Time Compiler). Start programu bývá pomalejší, protože stroj překládá společně využívané knihovny.
- Málo zranitelný kód – Aplikace se šíří jako zdrojový kód v CIL, není tedy úplně jednoduše lidsky čitelná.
- Přenositelnost – Je nejspíš jasné, že hotový program poběží na každém železe, na kterém se nachází virtuální stroj. To ale není vše, my jsme dokonce nezávislí i na samotném jazyce. Na jednom projektu může dělat více lidí, jeden např. v C#, druhý ve Visual Basic a třetí v C++. Zdrojové kódy se poté vždy přeloží do CIL.
Jazyky s virtuálním strojem ctí objektově orientované programování a jedná se o současný vrchol vývoje v této oblasti. Existují i jazyky 4. a 5. generace, ale ty mají specifické použití a zde se jimi zatím nebudeme zabývat.
.NET
Jak funguje C#, jsme si tedy vysvětlili, ještě si řekněme, co přesně je .NET. Rozumí se jím v zásadě čtyři věci: jazyk, Visual Studio, virtuální stroj (CLR) a knihovny.
Jazyk
Jak jsme se již zmínili, v .NET máme k dispozici několik jazyků, ve kterých můžeme vyvíjet. C# je z nich nejmodernější a byl přizpůsoben právě pro .NET.
Visual Studio
Visual Studio je IDE (Integrated Development Environment), tedy prostředí, ve kterém píšeme zdrojový kód a které nám také pomáhá s vývojem. VS je velmi uznávané i v řadách javistů, jedná se o moderní IDE, které je ve verzi Community poskytováno zdarma, a to i pro komerční účely.
Virtuální stroj
CLR je virtuální stroj, který interpretuje CIL do instrukcí fyzického procesoru.
Knihovny
Knihovny jsou asi největší výhodou .NET. Microsoft nám v podstatě dodává kompletní sadu knihoven, ve které máme předpřipravenou řadu struktur a komponent, např. pro práci s konzolí, databázemi, formulářovými prvky a podobně. Řešení jsou kvalitní a aktuální, jsou sdílené mezi jednotlivými jazyky. Jelikož MS je autorem i Windows, jejich komponenty hezky pasují a jsou pro jejich systém odladěné. Pro běh aplikací je potom nutné, aby na koncové stanici byla tatáž verze .NET, ve které byla aplikace vyvinuta. Dobrá zpráva je, že Windows vždy mají nějaký .NET v sobě.
Implementace .NET
.NET existuje v několika implementacích (vydáních). Pojďme si je také alespoň rychle představit.
.NET Framework
Jedná se o nejstarší implementaci .NET, která již není aktivně vyvíjená. Její nejnovější verze jsou však stále podporovány. Tato implementace běží pouze na systému Windows.
.NET Framework má následující strukturu:
V .NET Frameworku 2.0 vidíme samotný CLR (virtuální stroj) a základní knihovnu Base Class Library. Verze 3.0 přináší určité nové směry ve vývoji formulářových aplikací a procesů. Zajímavá pro nás bude zejména verze 3.5, která přinesla tzv. dotazovací jazyk LINQ, o němž si řekneme více později. Další verze umožňuje efektivně provozovat LINQ na vícejádrových procesorech. V roce 2012 pak ještě přibyla verze 4.5, ta např. zjednodušuje psaní asynchronních funkcí (o tom později).
.NET Core (.NET)
.NET Core je novější aktivně vyvíjená open-source implementace, která je náhradou za starší .NET Framework.
Od verze 5.0 se z názvu vypustilo slovo "Core", máme tedy například .NET 5.0 nebo .NET 6.0.
Na rozdíl od .NET Frameworku není tato implementace vázána jen na OS Windows, ale je pomocí ní možné vyvíjet aplikace i pro jiné systémy, jako je například Linux a od verze 6.0 i Android nebo iOS. Další její významnou vlastností je, že nemusí být nainstalována na hostujícím zařízení.
Mono
Mono vzniklo jako podpora .NET na Linuxu, v tomto směru bylo ovšem vytlačeno novějším .NET Core, do kterého byly některé prvky Mona implementovány. Právě díky Monu lze v .NET vyvíjet i pro jiné systémy než jen Windows. Mono používá také herní engine Unity, jelikož podporuje i herní konzole.
Nyní Mono vyvíjí společnost Xamarin (ve vlastnictví Microsoftu).
.NET Standard
Aby byla zajištěna určitá míra přenositelnosti kódu mezi různými implementacemi .NET, vznikl .NET Standard. Jedná se v podstatě o specifikaci, která určuje společnou funkcionalitu, kterou každá implementace .NET obsahuje.
Nyní víme, s čím to vlastně budeme pracovat.
V příští lekci, Visual Studio a první konzolová aplikace v C# .NET, si ukážeme práci s Visual Studiem a vytvoříme si svůj první program.