Platforma .NET 4. hodina “…dnes to bude ideologické…“
Aleš Keprt
[email protected] říjen 2006
Doporučená literatura 1. Duffy J. Professional .NET Framework 2.0.
Wrox Press, 2006. 2. Wikipedia – .NET Framework
Historie Win32 API (Windows NT – 1993) Java
Visual Basic
… .NET Framework (Visual Studio .NET – 2002) „Programovací platforma vládne max 10 let.“
C++ 1992-2002 (…a předtím Pascal) C# 2002-2012 Nutno chápat jako přibližný odhad
Nejstručnější vysvětlení .NETu „Dotnet je něco jako Java.“
Základy platformy jsou stejné jako u Javy Je to od Microsoftu Umožňuje to různé programovací jazyky Je to jen (nebo hlavně) pro Windows
Co .NET řeší Programování přímo pro Win32 API je složité C a C++ jsou již zastaralé nízkoúrovňové jazyky Např. Visual Basic nebo Delphi jsou modernější Nový trend: www stránky nikdo nedělá v C++ Win32 API potřebuje i COM to je také složité Doba pokročila, počítače jsou rychlejší Můžeme nechat víc práce na počítač a méně práce na programátory použijeme vyšší programovací jazyky Objektově orientované paradigma „vládne světu“ Windows ani Unix/Linux nejsou objet.orientované Složitost op.systémů si žádá objektové nadstavby
Programovací jazyky v .NETu Proč používáme nejvíc C#:
Je to jediný jazyk přímo vyvinutý pro .NET
C++/CLI
Další jazyky:
Visual Basic 7,8,9
Teprve od roku 2005, vhodné pro staré aplikace Umožňuje nízkoúrovňové a nativní programování Z Basicu 6 zbyl jen název...
J# = „Java pro .NET“
Asi nejpodobnější původnímu jazyku Podporována jen hodně stará verzi knihovny JDK
Dva praktické body 1. GUI V C++ rozumně nedají dělat GUI aplikace
Jde to, ale je to tak pracné, že to trvá roky…
.NET umí mnohem víc, i 3D grafiku v oknech
Je potřeba objektové rozhraní jednodušší a tedy rychlejší tvorba GUI Navíc Win32 API a GDI umí jen základní grafiku
2. Web Většina programů jsou dnes webové stránky Hodně se používají relační databáze Převládají skriptovací jazyky Jen máloco je horší než C++ pro www stránky ☺
Technický bod Win32 tu nebude věčně
Má problémy ovládat RAM nad 3GB
Win64 potřebuje jiné 64bitové „exáče“ .NET má jednotné „exáče“
Fungují i v Linuxu (zadáte mono program.exe) V roce 2100 pořád může .NET fungovat, ale Win32 EXE nepůjde spustit… Poznámka: Kdyby Microsoft nešel touto cestou,
zřejmě by jej převálcoval Sun a jeho Java.
Jednotné „exáče“? Java běží interpretovaně v JVM
Programy v .NET jsou překládané až při
spuštění a běží v CLR
CLR = Common Language Runtime Čili de facto stejný princip jako Java, jen je to rychlejší při běhu (JVM má starší design) EXE soubor obsahuje kód v IL C++ Asm Link Nativní EXE Run
C# IL Link EXE Run JIT Nativní
.NET řeší i další problémy… DLL hell
Totální chaos ve verzích DLL souborů Nulová bezpečnost systému Microsoft vynaložil miliony USD na dočasná řešení tohoto problému ve Widows 2000 a XP COM – deklarace na více místech
Registrace komponenty v systému je jedno místo, samotná komponenta v souboru je zvlášť Často se rozhodní verze komponenty a registru Příklad: kodeky Windows Media Playeru = peklo
Různé znakové sady unicode
Knihovny .NET má mnoho knihoven
BCL (Base Class Library) ADO.NET ASP.NET XML Windows Forms aj. Dobrá knihovna je důležitější než samotný jazyk!
Proto nedebatujeme o tom, který jazyk je lepší
Co je důležitější? C++ Assembler Delphi
Bezpečnost vs. Rychlost (bezchybnost)
.NET Java
(praktičnost)
Common Type System Všechny jazyky používají CTS (plus své typy) CTS je 100% bezpečný
Neexistuje nic jako „pointer na neznámou paměť“ Neexistuje nic jako „chyba přístupu do paměti“ Chyby nemohou nastat záměrně, ani omylem
Pozn. Kontrolu typové bezpečnosti lze vypnout
Např. C# pak „umí“ a zná i klasické poinetry * &
Kód je pak rychlejší, ale nebezpečný
CTS má vlastně dva režimy: safe a unsafe
Metadata Metadata = data o datech
Data poskytují informace o sobě
Vždy lze zjsitit, s jakým typem pracujeme a jaké ma další vlastnosti (atributy)
Atributy jsou například: const, unsigned apod.
Toto je zásadní plus oproti COM programování
Vsuvka – každý jazyk je jiný Každý jazyk má jiný typový systém
Přesto všechny mohou běžet v rámci CTS Díky CTS se rozdíly mezi jazyky často smazávají Vlastnosti C#:
Převážně imperativní a objektově orientovaný Převážně staticky typovaný Částečně také funkcionální
Funkce vyššího řádu, uzávěry, lambda výrazy, typová inference
Důsledek typové bezpečnosti CTS Nemůže nastat buffer overflow
Viry nemají šanci ☺
Nemůže se omylem něco zapsat do paměti
Už není pravda, že proces má nějakou svou lokální paměť a do ní si může zapisovat, co chce
Klasická paměť (bajty) už vlastně neexistuje
Máme jen objekty a pracovat můžeme jen s objekty Nelze přetypovat objekt na blok paměti a podívat se, co tam je…
Statické a dynamické typování Statické kontrola typů při překladu Podporuje brzké odhalování chyb v programech Programy běží rychleji Dynamické kontrola typů při běhu Umožňuje napsat věci, které by jinak nešly ☺ Programy mají kratší zdrojáky C++ používá hlavně statické typování Scheme používá hlavně dynamické typování CTS (pochopitelně) umožňuje obojí Ideální jazyky nabízejí obojí i programátorům
Typy Všechno je System.Object Typy se dělí na dvě základní skupiny: Referenční class, interface Hodnotové struct, enum, primitivní typy (čísla)
Jsou potomkem System.ValueType Struct nemůže obsahovat konstruktor bez parametrů
Struct nemůže dědit jinou třídu než ValueType
Ani jeho složky nemohou mít výchozí hodnoty Může ale implementovat rozhraní
Doporučení pro vaše typy: Dejte přednost deklaraci typu na bázi class Deklarace typu struct většinou není přínosem
Kolik to má bajtů…? Struct má přesně tolik bajtů, kolik je dat
Zjištění délky struktury: Je to unsafe operace Operátor sizeof(typ) Nutno uzavřít do bloku unsafe Funkce Marshal.SizeOf(Type) Nutno mít permisi na spouštění unsafe kódu
CLR umožňuje ovlivnit pořadí součásti struktury v paměti Velikost referenčních typů nelze zjistit (ani v bloku
unsafe)
Počítejte minimálně 4–8 bajtů navíc A ještě víc na 64bitových platformách
Boxing a unboxing
Mechanizmus sjednocení typů vše je objekt Boxing = zabalení hodnoty do objektu Unboxing = vybalení boxované hodnoty Na co je to potřeba:
Na hodnotách nelze volat virtuální metody Hodnoty nelze ukládat do kolekcí či polí
S výjimkou generických (od verze .NET 2.0)
C# (i další jazyky) provádí boxování automaticky object o = 3; int a = (int)o; Boxované hodnoty nelze měnit!
null Klíčové slovo null je beztypová objektová „nula“ Hodnotový typ nemůže nabýt hodnoty null Od verze .NET 2.0: System.Nullable
Umožňuje přiřazovat null do hodnotových typů Sám je také hodnotovým typem(!) Pozor! Funguje se zvláštní podporou v CLR C# nabízí otazníkovou syntaxi
int? a = null; int b = a ?? 2;
Ještě k boxování… Hodnotové typy nemají tabulku metod
Volání potřebující tabulku metod fungují pomocí
boxování
Hodnota se boxuje a na ní se volá daná metoda
Při HasValue==true se převede na bázový typ
Boxování Nullable:
int? a = 3; a.GetType() System.Int32, nikoliv Nullable
Při HasValue==false se převede na null
int? a = null; a.GetType() NullReferenceException
Přístup k součástem programu Programy se dělí na „assembly“
Většinou jeden EXE/DLL = assembly Jedno assembly může být i ve více souborech
Můžeme určit, které součásti (třídy, metody
apod.) budou „vidět“ a kým
Z C++ známe modifikátory public/protected/private C# má další modifikátory, také pro třídy CLR má ještě další modifikátory
Možnosti přístupu Public Volně přístupné pro všechny Private Omezuje přístup na oblast vlastní třídy Platí jen pro součásti tříd Family (C# protected) Omezuje přístup na vlastní třídu a potomky v dědičnosti Platí jen pro součásti tříd Assembly (C# internal) Omezuje přístup na vlastní assembly Family or Assembly (C# protected internal) Umožňuje přístup jako family a celému svému assembly Family and Assembly (C# nepodporuje) Omezuje přístup na family a jen v rámci assembly
Součásti typů Každý typ může mít součásti:
Vnořené typy Konstruktory Metody Fieldy (česky proměnné) Property (tady ani český termín není ☺) Události
Vnořování typů Typ může být deklarován uvnitř jiného typu
class A { class B {…} } Toto je stejné jako v C++
Vnitřní typ má přístup k private součástem
vnějšího typu a k protected součástem v rámci typové hierarchie vnějšího typu
Toto je „nečekaně“ také stejné jako v C++ ☺
Fieldy Prostě proměnné (stejné jako v C++) ☺
Mohou být statické jedinečné v rámci
aplikační domény (ekvivalent procesu)
Jednoduše řečeno: společné pro všechny instance
Modifikátory:
Readonly = možno nastavit jen v konstruktoru Static literal (C# const) = pravé konstanty
Referenční typy z principu nemohou být konstanty
Metody Kód programu se dá zapsat jedině do metody Existují i speciální metody (konstruktory apod.) Metody nikoho nepřekvapí – známe je z C++ Mohou být statické (pak nemají this)
Mohou mít lokální proměnné – též známe z C++ Mohou být přetížené Přetížené = stejný název, různé parametry Neexistují výchozí hodnoty u parametrů Lze to simulovat přetížením
Proměnlivý počet parametrů: CTS jej nativně podporuje C# jej nepodporuje nutno použít pole (param array)
Předávání parametrů metodám CTS podporuje dva způsoby (první je výchozí):
Pass-by-value = pass-by-copy
Hodnota se okopíruje Reference se okopíruje a ukazuje na stejný objekt
Pass-by-reference
Vytvoří se reference na hodnotu Vytvoří se reference na referenci(!!!) C# umožňuje i specificky výstupní parametry (out)
Výjimky CLR nativně nepodporuje bloky ve stylu { … } Bloky try-catch-finally jsou přeloženy do
handlerů výjimek
Jsou to samostatné části kódu v každé metodě Každý handler má označený offset kódu, pro který platí Výhodou tohoto řešení je velmi rychlý běh programu (Proč? Téma k vlastnímu zamyšlení.)
Konstruktory Hodnotové typy jsou vždy nulovány Můžete definovat konstruktor s parametry
Ale nelze zajistit, že bude zavolán(!) Čili hodnota může vzniknout i bez konstruktoru(!!)
Princip zřetězení konstruktorů (pomocí base a this)
Referenční typy vždy mají nějaký konstruktor CTS nevyžaduje volání konstruktoru předka C# to ale vyžaduje ☺
Výchozí hodnoty proměnných CTS nepodporuje Překladač C# to přeloží tak, že vloží inicializaci do kódu všech koncových konstruktorů Pozor! Výjimka v konstruktoru mine Dispach
Kdy je volán statický konstruktor?
Volání statického konstruktoru CTS volá statický konstruktor kdykoliv před
prvním použitím třídy
Současná implementace jej volá co nejpozději
Toto je velmi výhodné (ve srovnání s C++)
Program může sám vyžádat zavolání statického
konstruktoru
System.Runtime.CompilerServices.RuntimeHelpers. RunClassConstructor(typeof(T).TypeHandle);
Property CTS nezná žádné property – překvapení? ☺
Property jsou syntaktický cukr na úrovni metadat
Fyzicky to pochopitelně musí být metody s příslušným atributem
Indexer je v C# zvláštní typ property
V CTS je to výchozí metoda objektu Může být přetížený
Pozor na přetypování Koerce u hodnotových typů
Vždy vytváříme novou instanci! Příklad: (double)34
Přetypování u referenčních typů
Operátor as (C#) nikdy nevytváří novou instanci
Příklad: this as object Neplatné přetypování vrací null
Operátor op_Explicit (kulaté závorky v C#)
Může volat přetíženou implementaci operátoru Toto někdy může vytvořit novou instanci Neplatné přetypování vyvolá InvalidCastException
Abstraktní třídy Abstraktní metoda abstraktní třída
Obrácená implikace ale neplatí!
CTS pro ně má zvláštní model dědičnosti
Dědí jen signatury, nikoli implementace Fyzicky je to stejné jako u rozhraní
Pozor na rozhraní Třída má má jen jednu tabulku metod pro
implementované rozhraní
interface Rozhraní { int něco(); } class Předek : Rozhraní { public int něco() { return 1; } } class Potomek : Předek,Rozhraní { public int něco() { return 2; } } int Testuj(Potomek p) { return p.něco() – (p as Rozhraní).něco(); }
Jmenné prostory (namespace) CTS nezná jmenné prostory – překvapení? ☺ Každý jazyk to může implementovat po svém
Překladač jazyka musí všechny lokální názvy
nahradit celými jmény
Pár poznámek k delegátům Delegáty jsou v CLR velmi složitě
implementované
V C# vidíme jen špičku ledovce (díky bohu ☺)
Nativní delegát (System.Delegate) umí
odkazovat jen na jeden cíl C# používá System.MulticastDelegate, ten obsahuje seznam obyčejných delegátů Volání delegátů probíhá dynamicky
Tím je mimochodem umožněna kontravariance vstupů a kovariance výstupů …a je to o poznání pomalejší než pointery v C++
…a ještě k delegátům Anonymní metody nemají podporu v CTS
C# je překládá jako samostatné metody Nejsložitější je podpora vnějších proměnných
Tím vzniká podpora pro uzávěry
Poznámka: V Javě toto nejde udělat ☺
A ty jsou opět podporovány v C#, ale ne přímo v CTS (CTS prostě jen umožňuje toto vše naimplementovat)
Atributy Pozor! Proměnné nejsou atributy!!! Proměnná = field
Atribut = doplňující informace
Může být připojen k libovolné entitě programu Můžeme definovat i vlastní atributy
Problematika atributů je extrémně složitá
Vrátíme se k tomu později
V C# se atributy používají pomocí závorek [ … ]
Příklady atributů jsou v souboru AssemblyInfo.cs
Výčtové typy (enum) Výčtový typ je seznam pojmenovaných hodnot
nad nějakým bázovým číselným typem Čili je to číslo + atributy Je to tedy hodnotový typ
Atribut [Flags] umožňuje bitové kombinace Povolí používání bitových operátorů K dispozici jsou šikovné statické metody: GetValues – vrací seznam definovaných hodnot IsDefined – testuje, zda je hodnota definována
Do enumu totiž lze vložit libovolné číslo
Parse – převede jméno hodnoty na hodnotu
Zde je problém s překladem do cizích řečí
Konec přednášky