Vizuális és eseményvezérelt programozás BMF NIK
A .NET keretrendszer Definíció Vázlatos felépítés A köztes nyelv és a .NET futtatókörnyezet Menet közbeni fordítás és optimalizálás Egységes típusrendszer Automatikus memóriakezelés Szerelvények és verziókezelés Biztonsági modell Osztálykönyvtárak © Miklós Árpád, BMF NIK, 2006–2009
[email protected]
Hallgatói tájékoztató A jelen bemutatóban található adatok, tudnivalók és információk a számonkérendő anyag vázlatát képezik. Ismeretük szükséges, de nem elégséges feltétele a sikeres zárthelyinek, illetve vizsgának. Sikeres zárthelyihez, illetve vizsgához a jelen bemutató tartalmán felül a kötelező irodalomként megjelölt anyag, a gyakorlatokon szóban, illetve a táblán átadott tudnivalók ismerete, valamint a gyakorlatokon megoldott példák és az otthoni feldolgozás céljából kiadott feladatok önálló megoldásának képessége is szükséges.
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
1:
2
Mi a .NET keretrendszer? • A .NET keretrendszer („.NET Framework”) egy önálló programozási környezet az operációs rendszer szintje felett, amely – objektumorientált, bővíthető programozási felületet – számos kiegészítő szolgáltatást és – a korábbiaknál több szempontból is magasabb fokú biztonságot nyújtó
új absztrakciós rétegként ékelődik be a szoftveralkalmazások és az operációs rendszer közé. Ezt az absztrakciós réteget szokás „virtuális gép”-nek is nevezni, amely saját, nyelvi szinten objektumorientált programozási felületet megvalósító utasításkészlettel rendelkezik. A .NET keretrendszerre írt programok számára ez az utasításkészlet érhető el, futtatásukat pedig maga a keretrendszer végzi és felügyeli (ebből következően a .NET programok futtatásához szükség van a keretrendszerre is). Maga a keretrendszer elvileg bármely operációs rendszerre elkészíthető, ami a megírt programok számára a platformfüggetlenség lehetőségét kínálja fel. V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
1:
3
A .NET keretrendszer vázlatos felépítése .NET alapú alkalmazások
.NET keretrendszer ASP.NET osztálykönyvtár
Windows Forms osztálykönyvtár
Webszolgáltatások
Vezérlők
Grafikai eszközök
Vezérlők
Egyéb szolgáltatások
.NET osztálykönyvtár (Framework Class Library) ADO.NET
IO
Reflection
Management Remoting
Messaging
Security
Net
Threading
... XML
...
.NET futtatókörnyezet (Common Language Runtime) JIT fordító
Egységes típusrendszer
Memóriakezelés
Verziókezelés
Programkód ellenőrzése
Kompatibilitási réteg
Operációs rendszer V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
1:
4
A köztes nyelv és a .NET futtatókörnyezet • A .NET alapú alkalmazások által használható utasításkészletet egy ún. köztes nyelv határozza meg A köztes nyelv elnevezése „Intermediate Language” vagy „IL”, emellett szokás „CIL” („Common Intermediate Language”) néven is hivatkozni rá.
• A magasabb szintű .NET nyelveken (C#, Visual Basic.NET stb.) írt programokat erre a nyelvre fordítja le a megfelelő fordítóprogram • Futtatáskor a köztes nyelven létrejött köztes kódot menet közben ellenőrzi és fordítja le a keretrendszer megfelelő része (az ún. „futtatókörnyezet”) a tényleges hardverplatformon használt, a processzoron közvetlenül futtatható gépi kódra („natív kód”) A futtatókörnyezet neve „Common Language Runtime Execution Engine”, vagy röviden „CLR”. A keretrendszer által ellenőrzött és kézben tartott köztes kódú programot „felügyelt kód”-nak („managed code”) nevezzük.
• A natív gépi kódra lefordított, immár ellenőrzött és biztonságos programkódot az operációs rendszer futtatja a hardveren V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
1:
5
A köztes nyelv és a .NET futtatókörnyezet C# fordítóprogram .NET futtatókörnyezet
A .NET keretrendszerre C# nyelven megírt forráskód A forráskód lefordítása után előállt köztes (IL) kód
Amennyiben az elkészült programot x86 processzoron futtatjuk, az alábbi natív gépi kód készül el, majd fut le
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
1:
6
Menet közbeni fordítás és optimalizálás • A köztes kódú programok metódusait tehát natív gépi kódra kell fordítani ahhoz, hogy a processzor futtatni tudja őket • Ezt a feladatot a menet közbeni fordító („JIT fordító”, angolul „JIT compiler” vagy „just-in-time compiler”) végzi el A JIT fordító minden metódust az első híváskor fordít le natív gépi kódra. A fordítás eredményét eltárolja, így ezt követően a metódus újabb hívásai esetén már nincs szükség fordításra, ilyenkor a már lefordított gépi kód fut. Ebből következően a programok indításánál és az egyes metódusok első végrehajtásánál komoly sebességveszteség lép fel, ami azonban később, a program futása közben eltűnik. Az OOP általános jellemzője a metódushívások igen nagy száma és gyakori ismétlődése, így ez a megoldás teljesítmény szempontjából is jól illeszkedik az OOP paradigmához.
A menet közbeni fordítás lehetőséget ad a kód optimalizálására is. • Aktuális processzormodell, illetve hardverkonfiguráció észlelése és kihasználása • Egyes hardverfüggő feltételes utasítások eredménye futáskor előre látható, így ezek akár el is távolíthatók a programból (pl. „ha a processzorok száma > 1, akkor ..., egyébként ...”) • Számos szoftveres optimalizáció is végezhető (határfeltételek ellenőrzésének kihagyása, konstans kifejezések előre kiszámítása, ciklusok kifejtése, metódushívások kifejtése…) V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
1:
7
Menet közbeni fordítás és optimalizálás (1) Metódus hívása első alkalommal [A] Felügyelt program (hello.exe) class Program { static void Main() { string s = "Hello, World"; System.Console.WriteLine(s); System.Console.WriteLine(s); } }
CLR System.Console
[a Program.Main() metódusban közvetlenül vagy áttételesen hivatkozott egyéb .NET osztályok]
...
JITCompiler static void WriteLine(object)
JITCompiler
...
...
static void WriteLine(string)
JITCompiler ...
JITCompiler
MSCOREE.DLL
Natív kód (x86) 55 8B EC 57 56 53 83 EC 30 33 C0 ... ... 90 8D 65 F4 90 5B 5E 5F 5D C3 V1.2
2009. január 31.
A JITCompiler „metódus” pszeudokódja: 1. A kért osztályt (itt: System.Console) tartalmazó fájlból kikeresi azt a metódust, amelyet a futtatandó program éppen meghívott (itt: static void WriteLine(string)). 2. A kért osztályt tartalmazó fájlból betölti a fenti metódus IL kódját. 3. Lefoglalja a szükséges mennyiségű memóriát. 4. Az IL kódot natív kódra fordítja, és az eredményt eltárolja a 3. pontban lefoglalt memóriaterületen. 5. A kért osztályhoz tartozó fenti belső használatú táblázatban kicseréli a metódushoz automatikusan hozzárendelt kezdőcímet a most lefordított kód kezdőcímére. 6. Átadja a vezérlést a 3. pontban lefoglalt memóriaterületen elhelyezett natív kódnak. © Miklós Árpád, BMF NIK, 2006–2009
[email protected]
1:
8
Menet közbeni fordítás és optimalizálás (2) Metódus hívása a későbbiekben [A] Felügyelt program (hello.exe) class Program { static void Main() { string s = "Hello, World"; System.Console.WriteLine(s); System.Console.WriteLine(s); } }
CLR System.Console
[a Program.Main() metódusban közvetlenül vagy áttételesen hivatkozott egyéb .NET osztályok]
...
JITCompiler static void WriteLine(object)
JITCompiler
...
...
static void WriteLine(string)
WriteLine() natív kód ...
JITCompiler
MSCOREE.DLL
Natív kód (x86) 55 8B EC 57 56 53 83 EC 30 33 C0 ... ... 90 8D 65 F4 90 5B 5E 5F 5D C3 V1.2
2009. január 31.
A JITCompiler „metódus” pszeudokódja: 1. A kért osztályt (itt: System.Console) tartalmazó fájlból kikeresi azt a metódust, amelyet a futtatandó program éppen meghívott (itt: static void WriteLine(string)). 2. A kért osztályt tartalmazó fájlból betölti a fenti metódus IL kódját. 3. Lefoglalja a szükséges mennyiségű memóriát. 4. Az IL kódot natív kódra fordítja, és az eredményt eltárolja a 3. pontban lefoglalt memóriaterületen. 5. A kért osztályhoz tartozó fenti belső használatú táblázatban kicseréli a metódushoz automatikusan hozzárendelt kezdőcímet a most lefordított kód kezdőcímére. 6. Átadja a vezérlést a 3. pontban lefoglalt memóriaterületen elhelyezett natív kódnak. © Miklós Árpád, BMF NIK, 2006–2009
[email protected]
1:
9
Menet közbeni fordítás és optimalizálás (3) Előfordítás • Arra is van lehetőség, hogy teljes programokat vagy osztálykönyvtárakat a CLR előre lefordítson és eltároljon • Ezzel a megoldással még az első futtatáskor biztosan fellépő sebességveszteség is kiküszöbölhető A .NET keretrendszer része az „ngen.exe” nevű program („Native Image Generator”), amellyel az előfordítás elvégezhető. Az előfordított .NET programok vagy osztálykönyvtárak mindig egy konkrét processzorarchitektúrához kötődnek (pl. x86, x64 vagy Itanium), tehát csak korlátozott mértékben hordozhatók. Ezért a futtatókörnyezet együtt kezeli az előfordított elemeket és a hozzájuk tartozó eredeti IL kódot, és mindig ez utóbbit (tehát az eredeti fájlokat) tekinti mérvadónak. Ha bármilyen kétség merül fel az előfordított kód frisseségét vagy az aktuális architektúrának való megfelelését illetően, akkor a CLR úgy tekinti, mintha nem is létezne az előfordított kód.
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
1:
10
A .NET egységes típusrendszere • A .NET keretrendszer egységesen, a köztes nyelv szintjén rögzít bizonyos nyelvi tulajdonságokat és típusokat Ezek a tulajdonságok az IL (tehát a köztes kód) szintjén valósulnak meg, így minden olyan magasabb szintű nyelvre érvényesek, amelyhez létezik a .NET keretrendszert támogató, IL kódot készítő fordítóprogram.
• Az egységes típusrendszer neve angolul „Common Type System” vagy röviden „CTS” • A típusrendszer legfontosabb jellegzetességei: a) Objektumorientált felépítés, interfészek intenzív alkalmazása b) Nyelvfüggetlenség (a magasabb szintű nyelvek tekintetében) c) Szigorú típuskezelés d) Értéktípusok és referenciatípusok egyértelmű megkülönböztetése e) Átfogó kivételkezelés f) Attribútumok koncepciója
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
1:
11
A .NET egységes típusrendszere A CTS logikai szerkezete [B] Típus
Értéktípus
Referenciatípus
Interfésztípus
Felsorolás Beépített egyszerű típus
Mutatótípus Önleíró referenciatípus
Saját értéktípus (struktúra) sbyte, short, int, long, byte, ushort, uint, ulong, char, float, double, decimal, bool
Tömb
Osztálytípus
Képviselő
Dobozolt értéktípus Saját referenciatípus
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
1:
12
A .NET típusrendszerének jellemzői a) Objektumorientált felépítés • Az egységes típusrendszer teljes egészében objektumorientált Az IL nyelv az alapvető utasítások mellett részletesen megvalósítja az OOP legfontosabb alapelveit és bevált alapmegoldásait is: • • • • • •
osztályok és objektumok kezelése adatrejtés (láthatósági szintek) öröklés többalakúság absztrakt tagok interfészek
A köztes nyelv emellett az univerzális felhasználhatóság érdekében más speciális funkciókat is tartalmaz. Ilyenek például a „tail call” és a „tail callvirt” utasításpárok, amelyekre elsősorban a logikai programozási paradigma megvalósításaihoz lehet szükség. A Microsoft által készített .NET nyelvek közül csak a (nemhivatalos) F# funkcionális nyelv használja ezeket az utasításokat.
• A típusrendszer alapja a System.Object ősosztály Minden típus ennek az osztálynak a közvetlen vagy közvetett leszármazottja V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
1:
13
A .NET típusrendszerének jellemzői b) Nyelvfüggetlenség • A típusrendszer a következő lehetőségeket kínálja a rá épülő magas szintű programozási nyelvek számára: – – – –
Adott nyelven írt osztályból származtathatók osztályok más nyelven is Objektumok tartalmazhatnak más nyelven írt objektumokat is Objektumok közvetlenül hívhatják más nyelven írt objektumok metódusait is Metódusok nyelvi korlátozás nélkül adhatnak át egymásnak objektumokat
• A teljes típusrendszer jóval bővebb annál, mint amit egyetlen magas szintű programozási nyelv egymagában megvalósíthat A minden magas szintű .NET programozási nyelv számára kötelező funkciók és jellemzők közös részhalmaza a „közös nyelvspecifikáció”, angolul „Common Language Specification” vagy röviden CLS. Amennyiben egy program csak CLS-kompatibilis nyelvi jellemzőket használ, garantált, hogy bármely más .NET programozási nyelven írt másik program elemeivel is zökkenőmentesen együtt tud működni. Ehhez az is elegendő, ha a program nyilvánosan elérhető tagjaira teljesül a fenti korlátozás. V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
1:
14
A .NET típusrendszerének jellemzői A CLS, a CTS és a nyelvek viszonya Egységes típusrendszer (CTS)
Visual Basic
Felügyelt C++
Közös nyelvspecifikáció (CLS)
C#
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
1:
15
A .NET típusrendszerének jellemzői Magas szintű .NET programozási nyelvek • A kiterjedt egységes típusrendszernek köszönhetően szinte bármilyen létező programozási nyelv adaptálható a keretrendszerhez, de akár teljesen új nyelvek is definiálhatók • A Microsoft által készített .NET nyelvek: – – – – – –
C# (teljesen új nyelv a C, a C++ és a Java nyomdokain) Felügyelt C++ (.NET funkcionalitással bővített C++) Visual Basic.NET (.NET funkcionalitással bővített Visual Basic) J# (Java hasonmás) JScript (JavaScript hasonmás) F# (a Lisp-hez hasonló, a funkcionális és az OO paradigmát ötvöző nyelv)
• Más cégek és fejlesztők által készített .NET nyelvadaptációk: – Smalltalk, Pascal, Oberon, Delphi, Eiffel, Haskell, Lisp, Fortran, Cobol, Perl, PHP, Python, Ruby... • A fenti nyelvekhez kifejezetten a .NET-re épülő új nyelvváltozatot hoztak létre V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
1:
16
A .NET típusrendszerének jellemzői c) Szigorú típuskezelés • Minden változónak kötelezően van típusa – Típus nélküli adatok nem deklarálhatók és nem használhatók – A .NET programozási nyelveiben (a C++ kivételével) nincsenek mutatók – Minden egyes művelet eredménye egyértelműen meghatározott típusú
• A futtatókörnyezet mindig képes biztonságosan azonosítani az objektumok tényleges típusát Az objektumok tényleges típusa a GetType() metódussal mindig felderíthető, ezt a metódust ugyanis minden típus örökli a System.Object osztálytól. Mivel ez az örökölt metódus az ősosztályban nemvirtuális, lehetetlen, hogy egy objektum „hazudjon” a saját típusát illetően.
• A típusok (akár automatikusan, akár a programozó által) csak a futtatókörnyezet ellenőrzése alatt alakíthatók át egymásba Minden objektum automatikusan kezelhető ős típusú változókon keresztül is. Szándékos programozói típusátalakítás (angolul „casting”) is végezhető, de ha a forrás- és a céltípus nem kompatibilis, a futtatókörnyezet hibát jelez. V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
2:
17
A .NET típusrendszerének jellemzői A szigorú típuskezelés következményei • Bizonyos (kisebb mértékű) sebességveszteség A futtatókörnyezetnek minden műveletvégzés, illetve típusátalakítás során ellenőriznie kell az objektumok tényleges típusát.
• Nyelvek közötti átjárhatóság Ahhoz, hogy egy adott programozási nyelven megírt osztályból egy másik nyelven lehessen új osztályt származtatni, az új osztálynak ismernie kell az ős által használt összes adattípust. Hasonló okból egy objektum csak akkor tudja meghívni egy más programozási nyelven írt objektum metódusait, ha ismeri az általa használt típusokat. Ehhez az is szükséges, hogy a típusok leírása szerepeljen a programokban, típuskönyvtárakban.
• Automatikus memóriakezelés támogatása Az objektumok által használt memóriaterület automatikus felszabadításához a futtatókörnyezetnek fel kell tudnia deríteni az egyes objektumok típusát.
• Folyamatokon belüli önálló alkalmazástartomány (angolul „application domain”) koncepciójának támogatása V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
2:
18
A .NET típusrendszerének jellemzői d) Értéktípusok és referenciatípusok • Az értéktípusok és a referenciatípusok elsősorban az adatok kezelésében és a hozzáférés módjában különböznek egymástól A különféle referenciatípusokba tartozó változók (az értéktípusoktól eltérően) nem maguk tárolják az adatokat, csak hivatkoznak rájuk, azaz „referenciát” tartalmaznak a tényleges adatokra. Ez a megoldás elsősorban nagyobb adatmennyiségnél jelent előnyt, mivel így paraméterátadáskor vagy helyi változók használatánál nincs szükség a nagy mennyiségű adat többszöri másolására (elég, ha a hivatkozások másolódnak le), ami sokkal nagyobb teljesítmény elérését teszi lehetővé. A különféle értéktípusokba tartozó változók ezzel szemben közvetlenül tartalmazzák adataikat, így kezelésük sokkal egyszerűbb, létrehozásuk és megszüntetésük sokkal gyorsabban végrehajtható. Nagyobb mennyiségű adatot azonban nem célszerű így kezelni, elkerülendő a programok logikája szempontjából mindenképpen szükséges másolási műveleteket.
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
2:
19
A .NET típusrendszerének jellemzői Az érték- és a referenciatípusok viselkedése Értéktípus 1.
int i = 17;
int[] a = new int[2];
i
2.
4.
17
a
int j = i;
(ref)
null
null
int[] b = a;
j
3.
Referenciatípus
17
b
i = 23;
(ref)
a[0] = 15;
i
23
a
(ref)
j
17
b
(ref)
j = 36;
15
null
40
null
b[0] = 40;
i
23
a
(ref)
j
36
b
(ref)
5.
System.Console.WriteLine(i); // 23 System.Console.WriteLine(j); // 36
V1.2
2009. január 31.
System.Console.WriteLine(a[0]); // 40 (!) System.Console.WriteLine(b[0]); // 40
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
2:
20
A .NET típusrendszerének jellemzői Érték- és referenciatípusok összehasonlítása Érték- és referenciatípusok szemantikai összehasonlító táblázata Jellemző
Értéktípusok Az adatok közvetlenül a Adatok kezelése változókban helyezkednek el Adatok átadása Teljes másolással Általában egyszerű felépítésűek, Összetettség, példányaik kis méretűek méret (1–16 bájt) A veremben („stack”) vagy Tárolás mezőként más érték- vagy referenciatípusba ágyazva Deklarációval jönnek létre, és a Létrehozás, változók hatókörének végéig (a élettartam befoglaló blokk végéig) léteznek Ősük a System.ValueType típus, Öröklési leszármazottaik nem lehetnek, jellemzők interfészeket megvalósíthatnak V1.2
2009. január 31.
Referenciatípusok A változók csak hivatkoznak a tényleges adatra Hivatkozás másolásával Általában összetettebb felépítésűek, példányaik nagyobb méretűek (16 bájt – 2GB) A keretrendszer által automatikusan felügyelt memóriaterületen („managed heap”) Saját konstruktorral (new operátor) hozhatók létre, és addig léteznek, amíg van rájuk élő hivatkozás Ősük megválasztható, leszármazottaik lehetnek, interfészeket megvalósíthatnak
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
2:
21
A .NET típusrendszerének jellemzői Dobozolás és kicsomagolás • Az egységes öröklési hierarchia fenntartása érdekében az értéktípusok referenciatípussá alakíthatók, illetve később vissza is alakíthatók értéktípussá Az értéktípusok kezelhetők System.Object típusú változókon keresztül is, azaz például egy egész számot („int” típus) kezelhetünk objektumként (vagyis a „System.Object” típus egy példányaként) is. Ennek megvalósításához az értéktípus megfelelő példányát először át kell alakítani referenciatípussá (ez a művelet a „dobozolás”, angolul „boxing”). Amikor a „bedobozolt”, tehát immár hivatkozáson keresztül kezelt példányt ismét értéktípusként kívánjuk felhasználni, az értékét ki kell „csomagolni” az őt befoglaló referenciatípus belsejéből (ez a művelet a „kicsomagolás”, angolul „unboxing”). A .NET programozási nyelveiben (a C++ kivételével) a dobozolás és kicsomagolás mindig automatikusan történik, tehát a programozónak ezzel nincs külön feladata. Fejlesztésnél azonban célszerű úgy átgondolni a megtervezett és használni kívánt típusokat, hogy minél kevesebb dobozolás/kicsomagolás műveletpárra legyen szükség, mert ez komoly teljesítményveszteséget okozhat, amelynek a pontos okát általában igen nehéz felderíteni. V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
2:
22
A .NET típusrendszerének jellemzői Példa: dobozolás és kicsomagolás
Közvetlen adattárolás megfelelő típusú változóban
Dobozolás: egész számot tárolunk objektumként Kicsomagolás: objektumból egész számot veszünk ki
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
2:
23
A .NET típusrendszerének jellemzői e) Átfogó kivételkezelés • A programokon belüli hibakezeléshez a .NET típusrendszere egy általános, közösen elérhető, objektumorientált lehetőséget ad • Ez a megoldás a „kivételkezelés” (angolul „exception handling”) „Kivétel”-nek a programon belül bekövetkező nem várt eseményeket (hibák), illetve a kezelésükre szolgáló osztályokat nevezzük. A kivételkezelés alapelve a következő: minden programrészhez tartozhat egy másik, kivételkezelőnek elnevezett programrész, amely kizárólag az előbbi részben felmerülő bizonyos típusú hibák kezelésére hivatott. A kezelt hibák típusa tetszőlegesen szűkre, illetve bőségesre szabható. A hibakezelés .NET keretrendszerben alkalmazott megoldása lehetővé teszi, hogy a kivételeket kezelő programrész kapjon egy példányt a megfelelő kivételosztályból, amely bővebb adatokat szolgáltat a bekövetkezett hibáról. Tartalmazhat például kiírandó üzeneteket, a felmerült hiba pontos helyét és okát stb.
A .NET típusrendszere előre beépített kivételosztályok egész hierarchiáját tartalmazza, amely tetszőlegesen bővíthető újabb típusú kivételosztályokkal. V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
2:
24
A .NET típusrendszerének jellemzői A .NET előre definiált kivételosztályai System.Object
System.Exception IDictionary Data string HelpLink Exception InnerException string Message string Source string StackTrace MethodBase TargetSite
System.SystemException
V1.2
2009. január 31.
System.ApplicationException
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
2:
25
A .NET típusrendszerének jellemzői A .NET előre definiált kivételosztályai System.SystemException
System.ArgumentException System.ArithmeticException System.FormatException System.NotImplementedException System.NotSupportedException System.IO.IOException System.IndexOutOfRangeException System.InvalidCastException System.DivideByZeroException
System.StackOverflowException
System.OverflowException
System.OutOfMemoryException
...
System.ExecutionEngineException System.IO.FileNotFoundException
...
System.IO.FileLoadException System.IO.DirectoryNotFoundException
2.0 System.Runtime.CompilerServices. RuntimeWrappedException
... V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
2:
26
A .NET típusrendszerének jellemzői A kivételkezelés főbb előnyei és hátrányai Előnyök Átlátható hibakezelés
A hibakezelő programrészek világosan elkülöníthetők a feldolgozás logikáját megvalósító programrészektől, amelyek így az „ideális eset” feltételezésével írhatók meg.
Hatékonyabb hibakeresés
Hiba bekövetkezése esetén a futtatókörnyezet belülről kifelé haladva megkeresi az első alkalmas hibakezelő programrészt. A keresés során bejárt út végigkövethető, ami a kivételek által hordozott információkkal kiegészülve jóval könnyebben felderíthetővé teszi a hibát okozó programrészeket.
Hátrányok
Teljesítményveszteség
V1.2
2009. január 31.
A kivételek bekövetkezésekor a futtatókörnyezetnek példányt kell létrehoznia egy kivételosztályból, majd inicializálnia kell, ezután pedig meg kell keresnie az első alkalmas hibakezelőt. Ez ugyan időbe telik, de a teljesítményveszteség általában nem súlyos, mert hibák aránylag ritkán következnek be. (Ezért nem célszerű például kivételek bekövetkezését beépíteni a normál feldolgozás menetébe, vagyis szándékosan növelni a kivételek előfordulásának gyakoriságát.) © Miklós Árpád, BMF NIK, 2006–2009
[email protected]
2:
27
A .NET típusrendszerének jellemzői f) Attribútumok • Az attribútumok a .NET típusokhoz és tagjaikhoz kapcsolható, futási időben is lekérdezhető kiegészítő információk Az attribútumok segítségével a típusok és tagjaik tetszőleges jelzőkkel, tulajdonságokkal láthatók el, amelyek az adott típus vagy tag viselkedését leírhatják és módosíthatják. Meglétüket, illetve értéküket nemcsak fordításkor elemzi az adott .NET nyelv fordítóprogramja, hanem akár futási időben is felderíthetők, és az eredmények alapján a futó, az attribútumokat éppen vizsgáló metódusok döntéseket is hozhatnak. Azt a megoldást, amikor egy program futási időben saját maga felépítését, tulajdonságait elemzi, a .NET keretrendszer vonatkozásában reflexiónak (angolul „reflection”) nevezzük.
Ez a lehetőség tehát azt jelenti, hogy az attribútumok révén a programok viselkedése a forrásnyelv (például C#) elemeitől független, a programozó által definiálható, az egyes típusokat és tagjaikat leíró egyéb információkkal (úgynevezett metaadatokkal) befolyásolható.
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
2:
28
A .NET típusrendszerének jellemzői Attribútumok használata [Serializable] [ComVisible(true)] public class SpecialAttribute: Attribute { public SpecialAttribute() { }
Attribútumok
[WebMethod] public TestMethod1() { System.Console.WriteLine("Webszolgáltatásból elérhető metódus vagyok."); } [DllImport("kernel32.dll")] private static extern int GetCurrentProcessId(); }
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
2:
29
A .NET típusrendszerének jellemzői Példa: a FlagsAttribute attribútum használata using System; enum Szín { Színtelen = 0, Piros = 1, Zöld = 2, Kék = 4 }
using System; [Flags] enum Ételjellemző { Semmilyen = 0, Finom = 1, KellemesIllatú = 2, Fogyókúrás = 4 }
class Program { static void Main() { for (int i = 0; i < 8; i++) Console.WriteLine((Szín) i); } }
class Program { static void Main() { for (int i = 0; i < 8; i++) Console.WriteLine((Ételjellemző) i); } }
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
2:
Ha egy attribútum nevének végződése „Attribute”, akkor a végződés el is hagyható
30
A .NET típusrendszerének jellemzői Attribútumfajták • A .NET típusrendszerében háromféle attribútum létezik: – Beépített fordítási idejű attribútum A beépített attribútumokat a .NET fordítóprogramok ismerik és az általuk megszabott jellemzőknek megfelelően hajtják végre a fordítást. Ezek az attribútumok általában kulcsszóként jelennek meg az adott nyelvben. Ilyen attribútum például a „sealed”, a „readonly” vagy a „virtual”.
– Egyedi attribútum Az egyedi attribútumok lényegében a programozó által definiált osztályok, amelyek a System.Attribute osztály leszármazottai. Az egyedi attribútumok definíciójában megszabható, hogy milyen nyelvi elemekhez (osztály, interfész, metódus, paraméter stb.) kapcsolódhatnak, többször is szerepelhetnek-e egyazon nyelvi elemhez rendelve, illetve leszármazott osztályok megfelelő elemei örököljék-e az ősnél megadott attribútumot.
– Álegyedi attribútum Az „álegyedi” attribútumok olyan egyedi attribútumok, amelyek rendkívül gyakran fordulnak elő, ezért helytakarékossági és teljesítményokokból a .NET típusrendszere előre felismeri és speciális, tömörített formában tárolja őket. Ilyen attribútum például a System.SerializableAttribute vagy a System.Runtime.InteropServices.DllImportAttribute.
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
2:
31
Automatikus memóriakezelés • Objektumorientált rendszerekben az egyes típusok (osztályok) példányosításához és használatához memóriára van szükség • A .NET programozási környezetben a referenciatípusok memóriakezelésének főbb lépései a következők: 1. A típus egy példányához szükséges memória lefoglalása, amely a newobj IL utasítás meghívásakor automatikusan megtörténik A C# nyelvben például a new operátor használatakor kerül a fenti utasítás a köztes kódba.
2. A lefoglalt memóriában tárolandó kezdőértékek beállítása, a példány használható állapotba hozása Ezt a feladatot mindig a típus megfelelő konstruktora hajtja végre.
3. A típusból létrejött példány „életciklusának” fő részeként a következő lépés a hozzá tartozó tagok használata, akár többször egymás után ismételve 4. A példány használatának befejezésekor szükség lehet állapotmódosításra vagy az általa használt erőforrások korábbi állapotának visszaállítására Ezt a feladatot általában a típus destruktora hajtja végre.
5. A típusból létrehozott példány által használt memória felszabadítása A .NET automatikus memóriakezelője vállalja magára ezt a teendőt. V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
32
Automatikus memóriakezelés A szemétgyűjtő („garbage collector”) • A .NET memóriakezelője a lefoglalás és a felszabadítás lépéseit automatikusan elvégzi A két leggyakoribb programozói hiba a nem használt memóriaterületek felszabadításának elfelejtése, illetve a már felszabadított memória újbóli használata. Ezeket a hibákat a .NET felügyelt memóriakezelése teljes mértékben kiküszöböli, és sokkal kényelmesebbé is teszi a fejlesztést.
• A memóriakezelő azokat a memóriaterületeket szabadítja fel, amelyeket már egyetlen osztály egyetlen példánya sem használ Ennek megállapítása egyáltalán nem triviális feladat. A memóriakezelőnek azt a részét, amely a felszabadítható memóriaterületek megkeresését és a felszabadítás műveletét végzi, „szemétgyűjtőnek” nevezzük. A szemétgyűjtő külön szálon fut, és bizonyos feltételek fennállása esetén „felébred”, hogy memóriát szabadítson fel. Mivel ez komoly erőforrásigényű művelet, igen bonyolult algoritmusok biztosítják, hogy erre a lehető leggyorsabban és optimális időpontokban, csak szükség esetén kerüljön sor. A szemétgyűjtő algoritmus a System.GC osztály Collect() metódusán keresztül is meghívható. V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
33
Automatikus memóriakezelés Destruktorok • A destruktorok feladata hagyományosan a fenti 4. lépés, tehát a típus által használt erőforrások korábbi állapotának visszaállítása A .NET típusrendszerében erre az automatikus memóriakezelés következtében ritkán van szükség, ezért a .NET programozási nyelveiben csak speciális helyzetekre szokás destruktort készíteni. A destruktor valójában egy Finalize() nevű metódus, amelyet például a C# fordító nem enged meghívni még a típus saját kódjából sem, megakadályozandó, hogy a programozók elfelejtsék kezelni a kivételeket vagy elfelejtsék meghívni az őstípus destruktorát.
• Mivel a szemétgyűjtő futása a program szemszögéből nézve nem determinisztikus, nem lehet előre tudni, hogy a már nem használt objektumokon mikor fut le a típus destruktora Előfordulhat, hogy egy-egy típusnál nem célszerű vagy nem gazdaságos megvárni, amíg szükség lesz szemétgyűjtésre (például szűkös grafikai vagy adatbázis-erőforrások használata esetén). Erre az esetre megoldási lehetőségként az IDisposable nevű, egyetlen metódust (ez a Dispose() metódus) tartalmazó interfész megvalósítása kínálkozik. V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
34
Automatikus memóriakezelés A felügyelt memória („managed heap”) [A] Felügyelt memóriaterület A
B
C D E
F
G H
I
J
K Következő objektum helye
A C G K Hivatkozások Mezők Paraméterek Helyi változók CPU regiszterek
Destruktorhívást igénylő objektumok listája („finalization queue”)
Destruktorhívásra váró objektumok listája („freachable queue”) V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
35
Automatikus memóriakezelés A felügyelt memória („managed heap”) [A] Felügyelt memóriaterület (egy szemétgyűjtési ciklus után) A C D
F
G H
I
K Következő objektum helye
A C Destruktorhívást igénylő objektumok listája („finalization queue”)
Hivatkozások Mezők Paraméterek Helyi változók CPU regiszterek
G K Destruktorhívásra váró objektumok listája („freachable queue”)
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
36
Szerelvények és verziókezelés • A szerelvény (angolul „assembly”) a .NET keretrendszer köztes kódot tartalmazó, önleíró, biztonságosan azonosítható és verzionálható logikai tárolási (telepítési) egysége Egy szerelvény tetszőleges számú fájlból állhat, ám a .NET keretrendszer ettől függetlenül mindig egy egységként kezeli a szerelvényt.
• A szerelvények legfontosabb közös jellemzői: – A saját belső elemeiket, illetve a bennük lévő elemek külső függőségeit leíró metaadatokkal rendelkeznek, melyek összefoglaló neve „manifeszt” (angolul „manifest”) – Tartalmazzák a bennük található típusok metaadatait (leírását) és kódját – Egyértelmű verzióazonosító jellemzi őket, melynek segítségével biztosan, a tévedés lehetőségének kizárásával azonosíthatók • Amennyiben szükséges, a verzióadatok nyilvános kulcsú titkosítás segítségével állnak elő • Lehetőség van arra, hogy egy szerelvénynek egyszerre több verziója is aktív legyen
– Biztonsági információkat is tartalmazhatnak – Telepítésük általában egyszerű másolással megoldható V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
37
Szerelvények és verziókezelés A szerelvények felépítése Azonosító, fájlok listája,hivatkozások, biztonsági kérelmek, közzétett típusok
Szerelvény.dll Szerelvény metaadatai (manifeszt) Osztályok, struktúrák, metódusok, mezők...
Típusok metaadatai
Köztes (IL) programkód A szerelvényben tárolt típusokat ténylegesen megvalósító köztes kód Képek, hangok, ikonok, szöveges és egyéb erőforrások Erőforrások
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
38
Szerelvények és verziókezelés Metaadatok • A szerelvényeket leíró metaadatok (azaz a manifeszt) tartalma: 1. 2. 3. 4. 5.
Teljes azonosító (név, verzióadatok, kultúra, nyilvános kulcs kivonata) Tartalmazott fájlok listája (egy vagy több fájl) Hivatkozott szerelvények azonosítóinak listája (teljes azonosítók, lásd 1.) Biztonsági engedélykérelmek listája (a szerelvény elemeinek futtatásához szükséges jogosultságok felsorolása) Közzétett típusok listája (a szerelvény által tartalmazott nyilvános osztályok, struktúrák és egyéb nyelvi elemek)
• A metaadatok pl. az MSIL Disassembler eszközzel megtekinthetők A programot tartalmazó fájl neve „ildasm.exe”. Ez az eszköz a .NET keretrendszerhez külön letölthető fejlesztőkörnyezet része.
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
39
Szerelvények és verziókezelés Névterek, szerelvények és típusok viszonya [B] EgyikKomponens.dll
MásikKomponens.dll
Főprogram.exe
namespace BMF.NIK.Bemutatók.VEP.Keretrendszer
class Egyik
class Figyelő
class Másik
class Segéd
namespace BMF.NIK
class Program
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
40
Szerelvények és verziókezelés Privát és közös szerelvények • A privát szerelvények az alkalmazás könyvtárában (vagy annak bármely alkönyvtárában) elhelyezett, saját használatú modulok A privát szerelvények verziókezelése nem okoz problémát, telepítésük egyszerű másolással megoldható. Azonosításuk alapesetben nem szigorú, így bármikor frissíthetők új változatokkal, és ettől függetlenül automatikusan együttműködnek az adott alkalmazással.
• A közös szerelvények több különböző alkalmazás által közösen használt és közösen elérhető helyen tárolt modulok A közös szerelvényeknek egyedi azonosítóval kell rendelkezniük. A keretrendszer egy közösen elérhető helyen tárolja őket, telepítésük pedig csak a megfelelő segédeszközök valamelyikével történhet (pl. „gacutil.exe”). A megosztott tárolóhely neve „global assembly cache” vagy röviden „GAC”. Ez a tárolóhely biztosítja, hogy a benne tárolt közös szerelvényeknek párhuzamosan több verziója is aktív lehessen.
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
41
Szerelvények és verziókezelés Szerelvények biztonságos azonosítása • Az alábbi azonosítók különböző szerelvényeket határoznak meg: Főprogram, Version=1.0.8123.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Főprogram, Version=1.0.8123.0, Culture="en-US", PublicKeyToken=b77a5c561934e089 Főprogram, Version=2.0.1234.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Főprogram, Version=1.0.8123.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
• A fenti azonosítókat „erős név”-nek („strong name”) nevezzük A nyilvános kulcsú titkosítás használata garantálja, hogy egy erős névvel ellátott szerelvény nem hamisítható és nem módosítható (átnevezés, verziószám önkényes belső módosítása stb.), így minden körülmények között egyértelműen azonosítható.
• Ezek a szerelvények a GAC-ban egyszerre létezhetnek A szerelvény régebbi verzióját vagy más-más nyelvű (kultúrájú) változatát igénylő programok mindig automatikusan a nekik megfelelő szerelvényt kapják a keretrendszertől. Ez a viselkedés konfigurációs fájlokkal egyedi vagy központi szinten egyaránt módosítható. V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
42
Biztonsági modell • A .NET keretrendszer biztonsági modellje részletesen, finom szemcsézettséggel szabályozza a futtatott kódok erőforráshozzáférési jogosultságait A programokat a keretrendszer futtatáskor ún. tagsági feltételek alapján (ilyen például a származás helye, a szerelvényt kiadó cég azonosítója stb.) besorolja egy-egy kódcsoportba (angolul „code group”). A futtatott program jogosultságait az adott kódcsoportra vonatkozó jogosultságok (angolul „permissions”) gyűjteménye szabja meg, melyek egy része testreszabható (például a fájlrendszer használata, a nyomtatási lehetőségek, hálózati kommunikáció, felhasználói felület elemeinek használata stb.), más részét a keretrendszer maga állapítja meg (többek között a szerelvény neve, származási helye és kiadója alapján). A jogosultságok teljes gyűjteményét a .NET megfelelő biztonsági politikája (angolul „security policy”) határozza meg, amely három, egymást felülbírálni képes szintet kínál (felhasználói szint, számítógép szintje, vállalati szint). Az érvényes jogosultságok gyűjteményét az egyes szinteken kiválasztott jogosultságok metszete, azaz legkisebb közös részhalmaza szabja meg. V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
43
Biztonsági modell Szintek, kódcsoportok és jogosultságok [B] Felhasználói szint
Csoport: All_Code Jogosultság: Teljes Tagsági feltétel: Bármely kód
Vállalati szint
Csoport: All_Code Jogosultság: Semmi Tagsági feltétel: Bármely kód
Számítógép Csoport: MyComputer Jogosultság: Teljes Tagsági feltétel: Zóna
V1.2
2009. január 31.
szintjeCsoport: IntranetCsoport: All_Code Jogosultság: Semmi Jogosultság: Helyi intranet Tagsági Tagsági feltétel: Zónafeltétel: Bármely kód
Csoport: MyComputer Csoport: Intranet Csoport: https://intranet/ Jogosultság: Teljes Jogosultság: Helyi intranet Jogosultság: Teljes Tagsági feltétel: Zóna feltétel: Webhely Tagsági feltétel: Zóna Tagsági
Csoport: Internet Jogosultság: Internet Tagsági feltétel: Zóna
Csoport: https://intranet/ Jogosultság: Teljes Tagsági feltétel: Webhely
Csoport: BMF NIK Jogosultság: Teljes Tagsági feltétel: Kiadó
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
44
Biztonsági modell A biztonsági beállítások konfigurálása
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
45
A .NET osztálykönyvtárai • A .NET osztálykönyvtárai különböző névterekben több ezer előre megírt osztályt tartalmaznak, amelyek széles körű beépített funkcionalitást tesznek elérhetővé
ASP.NET osztálykönyvtár
Windows Forms osztálykönyvtár
Webszolgáltatások
Vezérlők
Grafikai eszközök
Vezérlők
Egyéb szolgáltatások
.NET osztálykönyvtár (Framework Class Library) ADO.NET Reflection
V1.2
2009. január 31.
IO
Management Remoting
Messaging
Security
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
Net
Threading
3:
... XML
...
46
A .NET osztálykönyvtárai Fontosabb támogatott alkalmazástípusok • Windows-alapú grafikus felülettel rendelkező programok Windows 2000, XP és Vista alkalmazások
• Windows-alapú konzolos alkalmazások Parancssoros ablakon keresztül kommunikáló programok
• Komponensek és osztálykönyvtárak Tetszőleges osztályok, vezérlők és komponensek gyűjteményei
• Háttérben futó rendszerszolgáltatások Felhasználói felület nélküli, a géppel együtt induló háttérszolgáltatások
• XML webszolgáltatások Távolról, http és https protokollon keresztül hívható metódusok
• Webes felülettel rendelkező programok Weboldalak és portálok
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
47
A .NET osztálykönyvtárai Fontosabb beépített névterek • • • • • • • • • • • • V1.2
System – alapvető típusok minden alkalmazáshoz System.Collections – gyűjtemények, vermek, sorok, listák, hasítótáblák... System.Diagnostics – alkalmazások hibakeresésének támogatása System.Drawing – kétdimenziós rajzolófunkciók System.IO – adatfolyam-alapú fájlkezelés, könyvtárak kezelése System.Net – hálózati kommunikáció System.Reflection – metaadatok és típusok futási idejű vizsgálata System.Runtime.Remoting – típusok és példányaik távoli elérése System.Runtime.Serialization – objektumok tárolása és visszaállítása System.Security – adatok és erőforrások védelme System.Threading – többszálú aszinkron programozás, párhuzamos erőforráselérés System.XML – XML sémák és XML formátumú adatfolyamok feldolgozása 2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
48
Ajánlott irodalom (1) [A] Jeffrey Richter: CLR via C#, Second Edition Kiadó: Microsoft Press, 2006 ISBN: 978-0-7356-2163-3 Web: http://www.wintellect.com/ Nyelv: angol Terjedelem: 736 oldal
[B] Christian Nagel, Bill Evjen, Jay Glynn, Morgan Skinner, Karli Watson, Allen Jones: Professional C# 2005 Kiadó: Wiley Publishing, Inc., 2006 ISBN: 978-0-7645-7534-1 Web: http://www.wiley.com/, http://www.wrox.com/ Nyelv: angol Terjedelem: 1540 oldal
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
49
Ajánlott irodalom (2) [C] Albert István, Balássy György, Dr. Charaf Hassan, Erdélyi Tibor, Horváth Ádám, Levendovszky Tihamér, Péteri Szilárd, Rajacsics Tamás: A .NET Framework és programozása Kiadó: Szak Kiadó, 2004 ISBN: 963-9131-62-8 Web: http://www.szak.hu/ Nyelv: magyar Terjedelem: 868 oldal
V1.2
2009. január 31.
© Miklós Árpád, BMF NIK, 2006–2009
[email protected]
3:
50