Professional Documents
Culture Documents
IllésZoltán C#
IllésZoltán C#
ILLS ZOLTN
Programozs C# nyelven
I. Alapismeretek
Minden jog fenntartva. Ezt a knyvet vagy annak rszleteit a kiad engedlye nlkl brmilyen formban vagy eszkzzel reproduklni, trolni s kzlni tilos. A knyv ksztse sorn a kiad s a szerz a legnagyobb gondossggal jrt el. Az esetleges hibkat s szrevteleket a jos@jos.hu e-mail cmen szvesen fogadjuk.
Szakmailag ellenrizte: Heizlern Bakonyi Viktria, ELTE Anyanyelvi lektor: Gulysn Felkai gnes Bort: Sarkadi Csaba, 2004 Kiad: Jedlik Oktatsi Stdi Bt. 1212 Budapest, Tncsics M. u. 92. Internet: http://www.jos.hu E-mail: jos@jos.hu Felels kiad: a Jedlik Oktatsi Stdi Bt. cgvezetje
Bevezet ................................................................................................... 11 I. Alapismeretek ....................................................................................... 13 I.1. A nyelv trtnete............................................................................ 13 I.2. A nyelv jellemzi........................................................................... 13 I.3. A .NET krnyezet ttekintse ........................................................ 15 I.4. A program szerkezete .................................................................... 16 I.5. Parancssori krnyezet hasznlata................................................... 20 I.6. A krnyezet hasznlata .................................................................. 21 I.7. Windows alkalmazsok ksztse .................................................. 25 I.8. Feladatok........................................................................................ 27 II. A C# nyelv alaptpusai ........................................................................ 28 II.1. Vltozk definilsa ..................................................................... 28 II.2. llandk definilsa ..................................................................... 29 II.3. Vltozk inicializlsa.................................................................. 29 II.4. Elemi tpusok................................................................................ 30 II.5. Felsorols tpus ............................................................................. 35 II.6. Feladatok ...................................................................................... 37 III. Kifejezsek, mveletek ...................................................................... 38 III.1. Egyoperandus opertorok.......................................................... 38 III.2. Ktoperandus opertorok .......................................................... 39 III.3. Hromoperandus opertor ......................................................... 42 III.4. Ktoperandus rtkad opertorok............................................ 43 III.5. Feladatok ..................................................................................... 46 IV. sszetett adattpusok.......................................................................... 47 IV.1. Tmbk ....................................................................................... 47 IV.2. Struktra...................................................................................... 51 IV.3. Feladatok..................................................................................... 54 V. Utastsok ............................................................................................ 56 V.1. sszetett utasts .......................................................................... 56 V.2. Kifejezs utasts.......................................................................... 56 V.3. Elgazs utasts........................................................................... 57 V.4. Ciklus utasts............................................................................... 59 V.5. Ugr utastsok............................................................................. 63 V.6. Feladatok ...................................................................................... 67 VI. Fggvnyek........................................................................................ 68 VI.1. A fggvnyek paramtertadsa ................................................. 68 VI.2. A Main fggvny paramterei .................................................... 72 VI.3. Fggvnyek vltoz szm paramterrel.................................... 74
I. Alapismeretek
VI.4. Fggvnynevek tdefinilsa...................................................... 75 VI.5. Delegltak, esemnyek................................................................ 77 VI.6. Feladatok..................................................................................... 80 VII. Osztlyok .......................................................................................... 81 VII.1. Osztlyok definilsa................................................................. 82 VII.2. Konstruktor- s destruktor fggvnyek ..................................... 84 VII.3. Konstans, csak olvashat mezk ............................................... 92 VII.4. Tulajdonsg, index fggvny..................................................... 94 VII.5. Osztlyok fggvnyparamterknt ............................................ 97 VII.6. Opertorok jradefinilsa......................................................... 98 VII.7. Interface definilsa................................................................. 104 VII.8. Osztlyok rkldse............................................................... 107 VII.9. Vgleges s absztrakt osztlyok .............................................. 110 VII.10. Virtulis tagfggvnyek, fggvnyelfeds ............................ 112 VII.11. Feladatok................................................................................ 117 VIII. Kivtelkezels ............................................................................... 118 VIII.1. Kivtelkezels hasznlata....................................................... 118 VIII.2. Sajt hibatpus definilsa ...................................................... 121 VIII.3. Feladatok ................................................................................ 125 IX. Input-Output..................................................................................... 126 IX.1. Standard input-output................................................................ 126 IX.2. Fjl input output ..................................................................... 129 IX.3. Feladatok................................................................................... 133 X. Prhuzamos programvgrehajts....................................................... 134 X.1. Szlak definilsa ....................................................................... 134 X.2. Szlak vezrlse ......................................................................... 135 X.3. Szlak szinkronizlsa................................................................ 138 X.4. Feladatok .................................................................................... 143 XI. Attribtumok.................................................................................... 144 XI.1. Attribtumok definilsa........................................................... 145 XI.2. Attribtumok hasznlata ........................................................... 146 XI.3. Knyvtri attribtumok............................................................. 151 XI.4. Feladatok................................................................................... 152 XII. Szabvnyos adatments .................................................................. 153 XII.1. Knyvtri tpusok szabvnyos mentse................................... 153 XII.2. Sajt tpusok szabvnyos mentse ........................................... 155 XII.3. Feladatok.................................................................................. 158 XIII. Knyvtrak, tvoli s web knyvtrak .......................................... 159 XIII.1. Helyi knyvtrak hasznlata .................................................. 159
XIII.2. Tvoli knyvtrhvs.............................................................. 162 XIII.3. Webknyvtrak hasznlata..................................................... 168 XIII.4. Feladatok ................................................................................ 173 XIV. Az elfeldolgoz ........................................................................... 174 XIV.1. Szimblumdefinci hasznlata ............................................. 174 XIV.2. Terleti jells........................................................................ 175 XIV.3. Feltteles fordts ................................................................... 176 XIV.4. Hibazenet.............................................................................. 176 XIV.5. Feladatok ................................................................................ 176 XV. Nem felgyelt kd hasznlata ........................................................ 177 XV.1. Nem felgyelt knyvtr elrse............................................... 177 XV.2. Mutatk hasznlata.................................................................. 178 XV.3. Feladatok ................................................................................. 179 XVI. Grafikus alkalmazsok alapjai ...................................................... 180 XVI.1. Windows alkalmazsok alapjai .............................................. 180 XVI.2. Webes alkalmazsok alapjai .................................................. 185 XVI.3. Feladatok ................................................................................ 189 Irodalomjegyzk..................................................................................... 190
Bevezet
Valamilyen programot megrni nem nehz, de j programot rni bizony nem egyszer feladat. Nehz lenne megmondani, hogy melyik az aranyt, amely a j programkszts iskoljnak tekinthet, de az bizonyosan llthat, hogy j s hatkony programot csakis megfelel fejlesztsi krnyezetben tudunk kszteni. Mai rohan vilgunkban a gyors gazdasgi, trsadalmi vltozsok mellett is szembetl, mennyire gyors, milyen dinamikus a vltozs az informatikban. Nem telik el gy hnap, hogy az informatika valamelyik terletn be ne jelentennek valamilyen jdonsgot, legyen az hardver, vagy szoftver. A szoftver fejlesztsi krnyezeteket tekintve az utbbi idk egyik legnagyobb s legtbb jdonsgot hoz egysgcsomagjt kaptk meg a fejlesztk az j Microsoft .NET rendszerrel. Ebben a krnyezetben, brmilyen terletre gondolunk, j technolgik, j lehetsgek segtik a fejlesztk munkjt (Common Language Runtime (clr), ASP.NET, stb.). Ismerjk mr: j msorhoz j frfi kell. Ezt az elvet alkalmazva a mr klasszikusnak tekinthet Basic s C++ nyelvek mellett megjelent az j C# (ejtsd: angolosan sz srp, magyarosan C kettskereszt, Cisz) programozsi nyelv a .NET rendszer rszeknt. A nyelv mottjnak taln a kvetkez kpletet tekinthetjk: A Basic egyszersge + a C++ hatkonysga = C#! Ebben a knyvben a fejlesztsi eszkztrnak ezt az alapjt, a C# programozsi nyelvet, annak lehetsgeit ismerhetik meg. Terveim szerint egy kvetkez knyvben a nyelv legfontosabb krnyezetbeli alkalmazsi lehetsgeit rszletesen trgyalni fogjuk. Remlem, hogy ez a knyv szles olvastbornak fog hasznos informcikat nyjtani. A programozssal most ismerkedknek egy j vilg j eszkzt mutatja meg, mg a programozsban jrtas Olvask taln ennek a knyvnek a segtsgvel megrzik azt, hogy ez az a nyelv, amit kerestek. Befejezsl remlem, hogy a magyarzatokhoz mellkelt pldaprogramok jl szolgljk a tanulsi folyamatot, s az anyag szerkesztse folytn nem kerltek bele nemkvnatos elemek. Vgl, de nem utolssorban meg kell ksznnm felesgemnek e knyv olvashatsgt segt munkjt. Ills Zoltn
11
I. Alapismeretek
I. Alapismeretek
I.1. A nyelv trtnete
A C# programozsi nyelv a Microsoft j fejlesztsi krnyezetvel, a 2002-ben megjelent Visual Studio.NET programcsomaggal, annak rszeknt jelent meg. Br a nyelv hossz mlttal nem rendelkezik, mindenkppen eldjnek tekinthetjk a C++ nyelvet, a nyelv szintaktikjt, szerkezeti felptst. A C, C++ nyelvekben kszlt alkalmazsok elksztshez gyakran hoszszabb fejlesztsi idre volt szksg, mint ms nyelvekben, pldul a MS Visual Basic esetn. A C, C++ nyelv komplexitsa, a fejlesztsek hosszabb idciklusa azt eredmnyezte, hogy a C, C++ programozk olyan nyelvet keressenek, amelyik jobb produktivitst eredmnyez, ugyanakkor megtartja a C, C++ hatkonysgt. Erre a problmra az idelis megolds a C# programozsi nyelv. A C# egy modern objektumorientlt nyelv, knyelmes s gyors lehetsget biztostva ahhoz, hogy .NET keretrendszer al alkalmazsokat ksztsnk, legyen az akr szmols, akr kommunikcis alkalmazs. A C# s a .NET keretrendszer alapja a Common Language Infrastructure(CLI).
13
I. Alapismeretek A keretrendszer fordtsi parancsa parancssorbl is egyszeren hasznlhat. (pl. csc /out:alma.exe alma.cs). Minden utasts helyre sszetett utasts (blokk) rhat. Az sszetett utastst a kapcsos zrjelek kz {} rt utastsok definiljk. rtk (alaptpusok, enum, struct, value) illetve referencia (class) tpus vltozk. Nincs mutathasznlat; biztonsgos a vektorhasznlat. Boxing, unboxing. Minden tpus se az object, gy pldul egy egsz tpust (int) csomagolhatunk objektumba (boxing) illetve vissza (unboxing). Fggvnyek defincii nem gyazhatk egymsba, nmagt meghvhatja (rekurzi). Teht fggvnydefinci esetn nincs blokkstruktra. Blokkon bell statikus vagy dinamikus lettartam vltozk deklarlhatk. Fggvnypolimorfizmus megengedett. rtk, referencia (ref) s output (out) fggvnyparamterek. Kezd paramter-rtkads, vltoz paramterszm fggvny deklarlsa. Delegltak, esemnyek hasznlata. Hierarchikus nvterekben hasznlt osztlyok. Mivel minden osztly, ezrt a program, a Main fggvny public static hozzfrs. Tbb osztly is tartalmazhat Main fggvnyt, de ilyen esetben a fordtskor meg kell mondani, hogy melyik osztlybeli Main fggvny legyen az aktulis indul (/main:osztlynv). j opertorok: is opertor egy objektum tpust ellenrzi (x is Labda), as opertor a bal oldali operandust jobb oldali tpuss konvertlja (Labda l = x as Labda;). A hagyomnyos konverzis opertortl abban klnbzik, hogy nem generl kivtelt! Privt konstruktor (nem akarunk egy pldnyt se), statikus konstruktor (statikus mezk inicializlsa, mindig pldny konstruktor eltt hvdik meg, futsi idben az osztlybetlt hvja meg) hasznlata. Nincs destruktor, helyette a keretrendszer szemtgyjtsi algoritmusa van. Szksg esetn az osztly Dispose metdusa jradefinilhat. Egyszeres rkls, interface-ek hasznlata. Opertorok definilsnak lehetsge, property, indexer definils. Kivtelkezels megvalstsa. Prhuzamos vgrehajts szlak definilhatsga.
I. Alapismeretek
I. Alapismeretek Az osztlyknyvtrak hasznlathoz egy fejleszt nyelvre van szksg. A Visual Studio.NET alaprtelmezsben hrom nyelvet biztost a fejlesztk szmra. A Visual Basic s a Visual C++ nyelveket, mint az eld keretrendszerbl megmaradt bzisnyelveket, s egy j nyelvet, amit a .NET keretrendszerhez fejlesztettek ki, a Visual C#-ot. Ma mr a Java utdnyelv, a J# is a Visual Studio.NET 2003 fejlesztrendszer rsze. Az j C# nyelvet szabvnyostottk, ami a szleskr elterjedsnek fontos felttele. A C# nyelv szabvnyostott dokumentcijhoz ECMA-334 kd alatt frhetnk hozz. A .NET keretrendszer lnyege, hogy a kzs nyelvi defincik mr szabvnyostottak. Ebben a szabvnyostsban a Microsoft mellett az informatikban rdekelt legnagyobb szervezetek is (HP, Intel, IBM, Sun, Fujitsu, Netscape) rszt vettek. Ez ECMA-335-s azonostval, mint a kzs nyelvi infrastruktra vagy eredeti nevn Common Language Infrastucture (CLI) nemzetkzi szabvnyv vlt.
I. Alapismeretek Fggvnyek defincijnak formja: visszaadott_tpus nv(argumentumlista, ha van) { vltoz defincik, deklarcik s utastsok } Az osztlyok egyikben kell egy Main nev fggvnynek szerepelnie, amely futtatskor az opercis rendszertl a vezrlst megkapja. A nyelv megengedi, hogy tbb tpusban (osztlyban) is definiljunk ilyen fggvnyt. Ebben az esetben fordtskor kell megmondani, hogy melyik tpus Main fggvnye legyen a fprogram. A programban hasznlt neveknek betvel vagy _ jellel kell kezddnik, majd a msodik karaktertl tetszleges bet s szm kombincija llhat. A nyelvben a kis- s nagybetk klnbzek, gy pldul a kvetkez kt nv sem azonos: alma aLma Az azonostnevek hossza ltalban 32 karakter lehet, de sok rendszerben az ignyeknek megfelelen lehet ezen vltoztatni. A .NET keretrendszer 16 bites unikd karakterbrzolst hasznl, amiben a magyar kezetes karakterek is benne vannak. A nyelvi fordt ezeket az kezetes betket is megengedi, gy az albbi nv is megengedett: krte Azonostk hasznlatra nem megengedettek a C#-ban a kvetkez kulcsszavak vagy vdett azonostk: abstract as base bool break byte case catch char checked class const continue decimal default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long namespace new null object operator out override params private protected public
I. Alapismeretek readonly short switch typeof ushort ref stackalloc this uint using return static throw ulong virtual sbyte string true unchecked void sealed struct try unsafe while
Egy forrsllomny szerkesztse sorn magyarzatokat is elhelyezhetnk a /* s */ jelek kztt. Az ilyen megjegyzs tbb soron t is tarthat. Egy soron bell a // jel utn rhatunk magyarzatot. A mai fejlesztkrnyezetekben egyltaln nem ritka, hogy valamilyen specilis megjegyzst arra hasznljanak fel, hogy ennek a programszvegbl trtn kigyjtsvel a forrsllomnynak vagy magnak a programnak egy dokumentcijt kapjk. Ezt a kigyjtst a fordt vgzi el. A C# fordtnak ha a /doc:fjlnv formban adunk egy fordtsi paramtert, akkor /// karakterek utni informcikat XML fjlba (a megadott nvvel) kigyjti. Ha nem parancssori fordtt hasznlunk, ami a Visual Studio.NET krnyezet hasznlatakor gyakran (majdnem mindig) elfordul, akkor ezt a belltst a projekt Tulajdonsgok dialgusablakban az XML Documentation File paramter rtkeknt llthatjuk be.
1. bra
Ha a keretrendszerben egy vltoz vagy fggvny defincija el beszrjuk a /// karaktereket, akkor azt a szvegszerkeszt automatikusan kiegszti a kvetkez formban:
I. Alapismeretek Plda:
/// <summary> /// ez egy vltoz /// </summary> int i; /// <summary> /// ez meg egy fggvny /// </summary> /// <param name="i"></param> public void szamol(int i) { }
A /** .*/ forma is megengedett, szintn dokumentcis clokra. Mivel az elz mdszer nem gyjti ki az ilyen formj megjegyzst, nem is hasznljk gyakran. Ezek alapjn nzzk meg a szoksosnak nevezhet bevezet programunk forrskdjt. Plda:
using System; class foci { static void Main() { Console.WriteLine("Hajr Fradi!"); } }
Programunk rvid magyarzataknt annyit mondhatunk, hogy a forrskdunk a legegyszerbb esetben egyetlen llomnybl ll, amiben nem definilunk nvteret, hanem csak egy foci osztlyt. (Valamilyen tpust kell definilnunk!) Ebben az osztlyban egyetlen fggvnyt definilunk, a programot jelent Main fggvnyt. Mivel egyetlen osztlytpus egyetlen pldnya sem ltezik a ltrehozsig (a definci mg nem ltrehozs!), ezrt ahhoz, hogy a fggvnynk pldny nlkl is ltezzen, a static jelzvel kell a hozzfrsi szintet meghatrozni. A C stlus nyelvek hagyomnyaknt a C# nyelvnek sem rszei a beolvas s kir utastsok, gy knyvtri szolgltatsokra kell hagyatkoznunk, ami a System nvtr rsze, s ennek a nvtrnek a Console osztlya biztostja a klasszikus kpernyre rs, Console.WriteLine() s billentyzetolvass, Console.ReadLine() feladatt.
I. Alapismeretek
A fordts eredmnye egy alma.exe llomny lesz, amit futtatva a kperny kvetkez sorban lthatjuk kedvenc buzdt mondatunkat. Termszetesen akkor kapunk hibamentes fordtsi eredmnyt, ha a fordtnk s a knyvtrak hasznlathoz szksges tvonali, krnyezeti vltoz belltsok helyesek. Ezt a vcvars32.bat llomny elvgzi. Ilyen parancssori krnyezetet legknnyebben a Visual Studio.NET programcsoportbeli segdeszkzk kzl tudunk elindtani. (Ekkor lefut a vcvars32.bat, nem kell neknk kzzel indtani!)
2. bra
A parancssori fordtnak a /? paramterrel trtn futtatsa, mint egy segtsg funkci, megadja a fordt fontosabb kapcsolit. Ezek kzl a legfontosabbak a kvetkezk: /t:exe alaprtelmezs, exe llomnyt fordt. /t:library a fordtand llomny knyvtr (dll) lesz. /out:nv a fordts eredmnynek nevt hatrozhatjuk meg, alaprtelmezsben ez a nv megegyezik a fordtott fjl nevvel. /r:valami.dll egy knyvtr felhasznlsa fordtskor, ha tbb knyvtri llomnyt kell hozzfordtani, akkor az llomnynevek kz vesszt kell tenni. /main:osztlynv a nyelv megengedi, hogy tbb osztly is tartalmazzon Main fggvnyt, ekkor ezzel a kapcsolval mondhatjuk meg, hogy a sok Main fggvny kzl melyik legyen a fprogram.
I. Alapismeretek A keletkezett exe llomnyrl el kell mondani, hogy annak futtatshoz nem elegend egy hagyomnyos 32 bites Microsoft opercis rendszer, gyakran ezt gy fogalmazzk meg, hogy a keletkezett program nem natv kdot tartalmaz, hanem szksges az opercis rendszerhez hozztelepteni a .NET keretrendszert! Ezt termszetesen a Visual Studio.NET installlsa elvgzi, gy a sajt gpnkn nem tnik fel annak hinya sem. Az irodalom ezt az exe kdot gyakran menedzselt (managed) kdnak nevezi. ltalban elmondhat, hogy az j fejlesztkrnyezet minden egyes nyelvi eszkze olyan kdot fordt, aminek szksge van erre a keretrendszerre. Termszetesen mint az let minden terletn, gy itt is vannak kivtelek. Ilyen kivtel pldul a C++ nyelv, ahol alaprtelmezs szerint meg kell mondani, hogy a programunkat menedzselt vagy natv kdra fordtsa-e a fordtnk. Natv kd alatt rtjk azt a fordtott eredmnyt, ami processzor szint utastsokat tartalmaz. Ebben a fejlesztkrnyezetben ezt a kdot a menedzselt ellentteknt, nem menedzselt (unmanaged) kdnak is nevezik.
I. Alapismeretek
3. bra
A New Project menpont kivlasztsa utn, ahogy az az albbi ablakban is ltszik, hrom f krdsre kell vlaszolnunk:
4. bra
I. Alapismeretek 1. Ki kell vlasztani a programozsi nyelvet. 2. Az adott nyelvhez meg kell mondani, hogy milyen jelleg alkalmazst szeretnnk kszteni. 3. Meg kell adni a munkaknyvtrat s a projekt nevt. Ebben a knyvben a nyelvet illeten mindig a Visual C# Project lehetsget vlasztjuk, amit a nyitott mappajel is mutat. A Templates ablakban vlaszthatjuk ki az alkalmazs jellegt. Jelen esetben, illetve a kvetkez rsz pldiban az n. Console Application lehetsget vlasztjuk, ami egy hagyomnyos karakteres fellet programkrnyezetet jelent. Ezek az alkalmazsok parancssori ablakban futnak. A munkaknyvtr s a projekt nevnek megadsa azt jelenti, hogy ltrehozza a munkaknyvtron bell a projekt nvvel megadott knyvtrat, esetnkben a c:\programok\hajra knyvtrat, s ezen bell egy nknyes class1.cs llomnyt, aminek tartalma a kvetkez:
5. bra
Ahogy lthat, a keretrendszer a class1.cs llomnyba mindent elkszt, hogy csak a valdi feladatra kelljen koncentrlnunk. Az llomny tartalma lnyegben megegyezik a korbbi els programkddal. Ahogy mr emltettem, nem ktelez nvteret (namespace) definilni, illetve nem ktelez a Main fggvny paramtert jellni, s a vgrehajtsi szl attribtum jellse is opcionlis.
I. Alapismeretek Ezeket, illetve a dokumentcis megjegyzseket figyelembe vve lthat, hogy a kt kdrszlet azonos. Amint a 3. brrl lthat, a fejlesztkrnyezet rendelkezik a mr szoksosnak nevezhet berskori rtelmezssel (IntelliSense), s ha ltala ismert tpust fedez fel, akkor egy helyi ablakban megmutatja az aktulis objektum elrhet jellemzit. A projekt a 3. brn lthat forrskd mellett mg egy assemblyinfo.cs llomnyt is tartalmaz, amiben hrom jellemz attribtum belltst vgezhetjk el. Bellthatjuk programunk jellemz adatait, verziszmt, illetve a digitlis alrs kulcsllomnyra vonatkoz informcit is. Ezek a tulajdonsgok a .NET keretrendszer szolgltatsain alapulnak, aminek rszletezse meghaladja ennek a knyvnek a kereteit. A programot a Debug menpont Start (F5) vagy Start without debugging (CTRL-F5) menpontjval fordthatjuk le, illetve futtathatjuk. Ez utbbi menpontot hasznlva a parancssori ablak nem tnik el a program futsa utn, lehetsget biztostva a program eredmnynek megnzsre.
6. bra
A fordts hatsra ltrejn a c:\programok\hajra knyvtrban egy bin s egy obj knyvtr. Ez utbbiban a lefordtott llomnyok, mg a bin knyvtrban egy Debug vagy Release knyvtrban ltrejn a kvnt exe program is. A kt vltozat kzti klnbsg a nevbl addik, nevezetesen a Debug vltozatban a nyomkvets elsegtst biztostva kszl el a futtathat llomny. Ez a lehetsg a programfejlesztsek sorn nagyon hasznos, hiszen logikai vagy egyb hibk keressben a lpsenknti, nyomkvet mdszerrel trtn vgrehajts nlklzhetetlen. A Release, kiadsi vgleges vltozatot a program befejezseknt az 5. bra fejlcben lthat Debug-Release vlasztmez lltsval kszthetjk el. Tbbfelhasznls krnyezetben, pldul Windows XP opercis rendszer alatt, a Debugger Users csoportba minden fejlesztt bele kell rakni. A knyv msodik rszben a C# nyelv elemeinek megismersekor jellemz projekttpusknt konzolalkalmazst (6. bra) hasznlunk.
I. Alapismeretek
7. bra
Miutn a fenti dialgusablakban befejezzk az adatok megadst, azt lthatjuk, hogy a karakteres alkalmazsokhoz kpest a munkafellet megvltozik, hiszen ebben a rendszerben az az alapelkpzels, hogy egy res ablak (form) az indul program. Ez valjban azt jelenti, hogy egy grafikus tervezablakot kapunk (Form1), amibe az eszkztrbl (Toolbox) a szksges vezrlelemeket a grafikus felletre visszk, s ekzben a forrskdot (form1.cs) a keretrendszer a felletalaktsnak megfelelen automatikusan mdostja.
I. Alapismeretek Az els grafikus programunkhoz hrom lpst vgezznk el! 1. rjuk t az ablak fejlcszvegt. Ehhez kattintsunk egyet a form-ra, majd a jobb als Properties (Tulajdonsgok) ablakban rjuk t a Text tulajdonsgot. (Els program!) 2. A Toolbox ablakbl helyezznk fel egy Button, nyomgomb objektumot. A Tulajdonsg ablakban lltsuk t a Text mezt a Vge szvegre. 3. Kattintsunk kettt a nyomgomb objektumra, ezzel a nyomgomb alaprtelmezett kattints esemny fggvnyt definiltuk. Ebbe rjuk be a Close(), ablakbezrs utastst. Ekkor a form1.cs forrskd rszlete a kvetkezkppen nz ki:
[STAThread] static void Main() { Application.Run(new Form1()); } private void button1_Click(object sender, System.EventArgs e) { Close(); }
Ezen hrom lps utn fordtsuk le, majd futtassuk a programot. Ezt, ahogy a korbbi karakteres program esetben is a Debug men Start menpontjval tehetjk meg. Ahhoz, hogy tovbbi grafikus alkalmazsokat tudjunk kszteni, elengedhetetlenl szksges, hogy ismerjk egyrszt a vlasztott nyelv lehetsgeit, msrszt a rendszer knyvtri szolgltatsait. Az elbbi, a nyelvi lehetsgek megismerse ltalban a legknnyebb s leggyorsabb feladat. Ez remnyeim szerint a kvetkez rsz ttanulmnyozsa utn a kedves Olvasnak is sikerl. Viszont az utbbi, a rendszer knyvtri szolgltatsainak megismerse hosszabb, tbb idt, sok egyni munkt jelent feladat. Azt remlem, hogy a befejez, a grafikus alkalmazsok alapjaival foglalkoz rsz utn mindenki elg btorsgot rez magban a tovbbi nll munka folytatshoz.
I. Alapismeretek
I.8. Feladatok
1. Milyen kd programot fordt a Visual Studio.NET fejlesztkrnyezet? 2. Mit csinl a Garbage Collection (szemtgyjt) algoritmus? 3. Lehet-e kezetes karaktereket hasznlni a C# programban? 4. Mik a Main fggvny jellemzi? 5. Egy program hny Main fggvnyt tartalmazhat, hogy tudjuk lefordtani?
Vltozk lehetnek klsk, azaz fggvnyen kvliek, vagy belsk, azaz fggvnyen belliek. A fggvnyen kvli vltozk is termszetesen csak osztlyon belliek lehetnek. Gyakran hvjk ezeket a vltozkat adatmezknek is. Bels vltozk, az adott blokkon (fggvnyen) belli loklis vltozk lehetnek dinamikus vagy statikus lettartamak. Mdost jelz nlkli definils esetn dinamikusnak vagy automatikusnak nevezzk, s ezek lettartama a blokkban val tartzkods idejre korltozdik. Ha a blokk vgrehajtsa befejezdtt, a dinamikus vltozk megsznnek. Statikus lettartam bels vltozt a static sz hasznlatval (ahogy kls vltoz esetn igen) nem definilhatunk. Lttuk, a fggvnyek lehetnek statikusak (lsd Main fggvny), melyekre ugyanaz igaz, mint az osztlyvltozkra, ezen fggvnyek lettartama is a programval egyezik meg, ms szval ezen fggvnyek a program indulsakor jnnek ltre.
28
II. A C# nyelv alaptpusai A vltozkat kt kategriba sorolhatjuk, az osztlytpus vltozk referencia tpusak, melyek mindig a dinamikus memriban helyezkednek el (az irodalomban ezt gyakran heap-nek nevezik), mg minden ms nem osztlytpus, az gynevezett rtktpus (value type) vltoz. Az rtktpus vltozkat szoktk stack vltozknak is nevezni. Az rtktpus vltozk kezdrtkt, az inicializls hinyban, 0, false, null rtkre lltja be a fordt. A vltozk definilsakor rgtn elvgezhet azok direkt inicializlsa is.
//eredmny Test //eredmny 5 //helyi vltoz alma ) ; //eredmny 6 vltoz.alma ); //a kls takart (5) //vltozra hivatkozs Console.WriteLine( terlet(r)); //a terlet fggvny // meghvsa // fggvnydefinci
"Teszt"); alma );
Br mg nem definiltunk fggvnyeket, gy taln korainak tnhet ez a plda, de inkbb felhvnm mg egyszer a figyelmet az kezetes karakterek hasznlatra. A ksbbi mintafeladatokban, ha elfordul kezet nlkli vltoz, fggvnydefinci, akkor az csak a korbbi krnyezetek rossz uthatsnak ksznhet. Egy osztlyon bell a fggvnyek definilsi sorrendje nem lnyeges. Sok krnyezetben furcsa lehet amit a fenti pldban ltunk, hogy elbb hasznljuk, s csak ezutn definiljuk a fggvnynket. (terlet fggvny)
II. A C# nyelv alaptpusai A karakter tpus 16 bites karakterbrzolst (unikd) hasznl. ltalban igaz, hogy minden alaptpus mrete rgztett. A karakter tpus vltoz rtkt aposztrf (') jelek kztt tudjuk megadni. Plda:
char c; c='a';
A backslash (\) karakter specilis jelentssel br. Az utna kvetkez karakter(eke)t, mint egy escape szekvencit dolgozza fl a fordt. Az gy hasznlhat escape szekvencik a kvetkezk: \a \b \f \r \n a 7-es kd csipogs backspace, elz karakter trlse formfeed, soremels karakter kocsi vissza karakter j sor karakter (soremels+kocsi vissza)
Az j sor karakter hatsa azonos a formfeed s a kocsi vissza karakterek hatsval. \t \v \\ \' \" \? \uxxyy tabultor karakter fggleges tabultor backslash karakter aposztrf idzjel krdjel xx s yy unikd karakter
string karaktersorozat
A System.String osztlynak megfelel tpus. Szvegek kztt a + s a += szvegsszefzst vgz opertorok ismertek. A [] opertor a szveg adott index karaktert adja meg. Az indexels 0-val kezddik. A @ karakter kikszbli a szvegen belli rzkeny karakterek hatst. Ilyen pldul a backslash (\) karakter. Plda:
char c='\u001b'; string s="alma"; string n="alma"+"barack"; s+="fa"; // c= a 27-es kd (Esc) karakterrel //s= almafa
A String osztly a fenti lehetsgeken kvl egy sor fggvnnyel teszi hasznlhatbb ezt a tpust. Ezen fggvnyek kzl a legfontosabbak: Length Csak olvashat tulajdonsg, megadja a szveg karaktereinek a szmt:
string s="alma"; int i=s.Length; //i=4
IndexOf(string) Tbb alakja van, megadja, hogy az eredetiben melyik indexnl tallhat a paramterl kapott szveg. A visszaadott rtk 1 lesz, ha nincs benn a keresett szveg:
int i="almafa".IndexOf("fa"); //4
Insert(int,string) A msodik paramterl kapott szveget, az els paramterrel megadott indextl beszrja az eredeti szvegbe:
A szvegtpus tovbbi szolgltatsait, fggvnyeit a szvegosztly (System.String) online dokumentcijban rdemes megnzni. Meg kell emlteni mg azt, hogy a szvegosztly fggvnyei nem mdostjk az eredeti szveget, szvegobjektumot, pldaknt az elz s szveges vltoz rtke vltozatlan marad. Szveges feldolgozsi feladatok sorn a regulris kifejezsekkel megadhat szvegmintk segtsgt is ignybe vehetjk. A .NET Framework a Perl5 kompatibilis regulris kifejezshasznlatot tmogatja. A Regex osztly szolgltatja a regulris kifejezst, mg a Match a tallati eredmnyt. Az osztlyokat a System.Text.RegularExpressions nvtrben talljuk. Plda:
using System; using System.Text.RegularExpressions; class regulris { public static void Main() { Regex reg_kif = new Regex("fradi"); // a fradi keresse Match tallat = reg_kif.Match("A Fradi j csapat?"); if (tallat.Success) { // (hol talltuk meg Console.WriteLine("A tallat helye: " + tallat.Index); } } }
A fenti plda nem ad eredmnyt, hiszen alaprtelmezsben a kis- s nagybet klnbzik, mg ha a regulris kifejezst egy kicsit mdostjuk, az albbiak szerint:
Regex reg_kif = new Regex("adi");
8. bra
Ha azt szeretnnk elrni, hogy az eredeti szvegnk is vltozzon, akkor ehhez a System.Text nvtr StringBuilder osztlyt tudjuk ignybe venni. Plda:
using System.Text; StringBuilder s1 = new StringBuilder("almafa alatt"); s1.Insert(4," a "); Console.WriteLine(s1); // "alma a fa alatt"
Mindkt egsz tpus eljeles, ha erre nincs szksgnk, hasznlhatjuk az eljel nlkli vltozatukat, melyek: uint, ushort, byte, ulong. Vals szmok definilsakor a 10-es kitevt jell e konstans hasznlhat. Plda:
float a=1.6e-3; // 1.6 * 10-3
Az imnti fggvny paramternek jellse referencia szerinti paramtertadst jelent, amirl a Fggvnyek c. fejezetben rszletesen szlunk.
Ekkor a 0,1, rtkek rendeldnek hozz a felsorolt nevekhez, s a nevek kirsakor ezen szmokat is ltjuk. A kezdrtkads lehetsgvel lve nem kell ezeket felttlenl elfogadnunk, hanem mi is megadhatjuk az rtkket. Plda:
class Szinek { enum jszinek {piros=4, kk=7, zld=8, srga=12}; public static void Main()
} }
A fenti ciklus eredmnyeknt azon egszek esetn, ahol az egsz rtkhez egy nevet rendeltnk hozz, a nv kerl kirsra, egybknt a szm. Az eredmny a kvetkez lesz:
kk zld 9 10 11
Mivel ez a tpus a System.Enum megfelelje, ezrt rendelkezik annak jellemzivel is. Ezek kzl a kt legjellemzbb a GetHashCode() s a ToString() fggvny. Az elbbi a bels trolsi formt, a megfelel egsz szmot adja meg, mg a ToString(), mint alaprtelmezett reprezentci, a szveges alakot (kk,zld, stb) adja meg. Plda:
jszinek s=jszinek.piros; Console.WriteLine(s.GetHashCode()); // eredmny: 4
A felsorols tpus alaprtelmezsben egsz tpus rtkeket vesz fel. Ha ez nem megfelel, akr byte (vagy tetszleges egsz szinonima) tpus rtkeket is felvehet gy, hogy a tpusnv utn kettsponttal elvlasztva megadom a tpusnevet. (Nem adhatom meg a vals vagy karakter tpust!) Plda:
enum sznek:byte {piros,kk,zld,srga}; enum hibs:float {rossz1, rossz2}; // ez fordtsi hiba
Elfordulhat, hogy olyan felsorolsadatokra van szksgem, melyek nem egy egsz konstanshoz, hanem egy bithez ktdnek, hiszen ekkor a logikai
II. A C# nyelv alaptpusai s/vagy mveletekkel a felsorolsadatok kombincijt hatrozhatjuk meg. Ebben az esetben a [Flags] attribtumot kell az enum szcska el szrni. Plda:
[Flags] enum alma {piros=1,jonatn=2,zld=4,golden=8}; alma a=alma.piros | alma.jonatn; Console.WriteLine(a); // piros, jonatn a=(alma) System.Enum.Parse(typeof(alma),"zld,golden"); // a felsorols tpus egyszer rtkadsa helyett // a knyvtri hvs lehetsgt is hasznlhatjuk // Console.WriteLine(a.GetHashCode()); // eredmny 12 lesz
Bithez kttt rtkek esetn ktelez minden egyes konstans nvhez megadni a neki megfelel bites brzolst! Az alaptpusokat a .NET keretrendszer biztostja, gy ennek a fejlesztsi krnyezetnek egy msik nyelvben pontosan ezek a tpusok llnak rendelkezsre. Az termszetesen elfordulhat, hogy nem ezekkel a nevekkel kell rjuk hivatkozni, de a nyelvi fordt biztosan ezen rtelmezs szerinti kdot (kztes kd) fordtja le a keretrendszer, mint futtat krnyezet szmra. Az alaptpusok zrsaknt meg kell jegyezni, hogy a mutat tpus is rtelmezett, ahogy a C++ vilgban, de ennek a hasznlata csak olyan C# programrszben megengedett, amely nem biztonsgos krnyezetben helyezkedik el (unsafe context). Errl rviden a knyv XIV. fejezetben olvashat.
II.6. Feladatok
1. Milyen alaptpusokat ismer a C# nyelv? 2. Mi a vltoz s az lland kztt a klnbsg? 3. Mi a klnbsg egy statikus s egy dinamikus lettartam vltoz kztt? 4. Definiljon kt szveg tpus vltozt, adja meg a hosszukat! 5. brzolja felsorols tpussal az NB 1 bajnoksg csapatait!
A new utasts gyakran szerepel a vektorokkal sszefggsben, amirl ksbb rszletesen szlunk.
38
III. Kifejezsek, mveletek A .NET keretrendszer egyik legfontosabb tulajdonsga az, hogy a dinamikusan foglalt memriaterleteket automatikusan visszacsatolja a felhasznlhat memriatartomnyba, ha arra a memrira a programnak mr nincs szksge. Sok nyelvi krnyezetben erre a delete opertor szolgl. ! ~ ++,-(tpus) kifejezs Plda:
double d=2.3; int i=(int) d; // i=2
aritmetikai negls logikai negls (not) bitenknti negls, inc, dec. tpusknyszerts
A ++ s -- opertor szerepelhet mind pre-, mind postfix formban. Prefix esetben a vltoz az opertorral vltoztatott rtkt adja egy kifejezs kirtkelsekor, mg postfix esetben az eredetit. Plda:
a= ++b; a= b++; // hatsa: b=b+1; a=b; // hatsa: a=b; b=b+1;
Az egyoperandus opertorok s az rtkads opertora esetn a vgrehajts jobbrl balra haladva trtnik, minden ms opertor esetn azonos precedencinl balrl jobbra.
E hrom opertorral mindig igaz: az (a/b)*b+a%b kifejezs az a rtkt adja. (% opertor esetn az operandusok nem lehetnek valsak, s a prioritsuk azonos.)
III. Kifejezsek, mveletek + << >> sszeads, string esetn azok sszefzse kivons bitenknti balra lptets bitenknti jobbra lptets
A jobbra lptets opertorhoz pldnak tekintsk az a >> b; utastst. Ekkor ha az a unsigned, akkor balrl nullval, klnben pedig az eljelbittel tlt a bitenknti jobbra lptets opertora. Plda: int a= 1, b; b= a >> 2; <,> <=, >= ==, != & ^ | && || // b rtke -1 marad
kisebb, nagyobb relcis opertorok kisebb vagy egyenl, ill. a nagyobb vagy egyenl opertorok egyenl, nem egyenl relcis opertorok bitenknti s bitenknti kizr vagy bitenknti vagy logikai s logikai vagy
is Logikai opertor, egy objektumrl megmondja, hogy a bal oldali operandus a jobb oldali tpusnak egy vltozja-e. Plda:
int i=3; if (i is int) Console.WriteLine("Bizony az i egsz!"); else Console.WriteLine("Bizony az i nem egsz!");
as Ktoperandus tpusknyszerts. A bal oldali vltozt a jobb oldali referencia tpusra alaktja, ha tudja. Ha sikertelen az talakts, akkor eredmnyl a null rtket adja. Plda:
double d=2.5; Object o= d as Object; Console.WriteLine(o); // eredmny: 2.5 // Object-re mindent lehet alaktani, aminek van toString kir //fggvnye. Errl bvebben ksbb esik sz.
III. Kifejezsek, mveletek typeof Egy System.Type tpus objektumot kszt. Ennek az objektumnak a mezfggvnyeivel, tulajdonsgaival (FullName, GetType()) tudunk tpusinformcihoz jutni. Plda:
using System; class Teszt { static void Main(){ Type[] t = { typeof(int), typeof(string), typeof(double), typeof(void) }; for (int i = 0; i < t.Length; i++) { Console.WriteLine(t[i].FullName); } } }
A tpuskonverzival kapcsolatban elmondhat, hogy minden rtktpusbl ltrehozhatunk egy neki megfelel Object tpus objektumot. Ezt gyakran boxing-nak, csomagolsnak, mg az ellenkez kicsomagol mveletet, amihez a zrjeles tpuskonverzi opertort kell hasznlni, unboxing-nak nevezi a szakirodalom. Plda:
int i=5; Object o=i; int j=(int) o; // boxing, becsomagols // unboxing, kicsomagols
Az Object tpus, ami a System.Object tpusnak felel meg, minden tpus seknt tekinthet. Ennek a tpusnak a fggvnyei ily mdon minden ltalunk hasznlt tpushoz rendelkezsre llnak.
III. Kifejezsek, mveletek Az Object tpus tagfggvnyei a kvetkezk: ToString() Megadja az objektum szveges reprezentcijt. Ha erre van szksg, pldul kirsnl, akkor ezt automatikusan meghvja. Ha ezt egy j tpushoz jradefiniljuk, akkor ez hvdik meg kirs esetn.
Console.WriteLine(o); // indirekt ToString hvs Console.WriteLine(o.ToString());
GetType() Megadja az objektum tpust, hasonl eredmnyt ad, mint a korbban ltott typeof opertor. Equals(object) Megadja, hogy kt objektum egyenl-e, logikai rtket ad eredmnyl.
int i=5; object o=i; Console.WriteLine(o.Equals(5));
Az Equals fggvnynek ltezik egy statikus vltozata is, aminek a formja: Object.Equals(object, object) GetHashCode() Megadja az objektum hash kdjt, ami egy egsz szm. Tetszleges sajt utdtpusban jradefinilhatjuk, amivel a sajt tpusunk hash kdjt tudjuk szmolni.
III. Kifejezsek, mveletek Az a vltoz vagy a 0-9 vagy 1 rtket kapja. A hromoperandus opertor valjban egy logikai elgazs utasts. A hatkony kifejezskszts, tmrebb rsmd kivl eszkze.
A nyelvben az rtkads sajtos, nmaga is kifejezs. Az egyenlsgjel bal oldaln olyan kifejezs, vltoz llhat, amely ltal kpviselt adat j rtket vehet fel. Gyakran hvja a szakirodalom ezt balrtknek is (lvalue). Az egyenlsgjel jobb oldaln egy rtket ad kifejezs kell, hogy lljon (jobbrtk, rvalue). Ez gyakorlatilag azt jelenti, hogy a jobbrtkre semmilyen korltozs nincs. Az rtkads sorn a bal oldal megkapja a jobb oldali kifejezs rtkt, s egyben ez lesz a kifejezs rtke is. Plda:
char []d=new char[80]; // msoljuk az s forrsszveget d-be while (i<s.Length) { d[i]=s[i]; i++; } char []c={'L','a','l','i'}; d=c; // hiba!! mivel d mr egy 80 karakteres //terletet jell, ezrt j terletet mr nem // jellhet, d nem lehet balrtk
Az rtkads opertora jobbrl balra csoportost, ezrt pl. az a=b=2; utasts hatsra a s b is 2 lesz. Az egyenlsgjel mellett mg nhny, az aritmetikai opertorokkal 'kombinlt' rtkad opertor is hasznlhat. Ezek az opertorok a kvetkezk: +=, =, *=, /=, %=, >>=, <<=, &=, ^=, |= Jelentsk: az e1 opertor e2 kifejezs, ahol e1 s e2 is kifejezsek, az e1 = e1 op e2 kifejezsnek felel meg, ahol op az egyenlsgjel eltti opertor.
A tpusok egyms kzti konverzijval kapcsolatban azt lehet mondani, hogy a C vagy C++-ban ismert automatikus konverzik nem lteznek. Egy egsz tpus vltozt egy valsba gond nlkl berhatunk, mg fordtva mr hibt jelez a fordt. A konverzis lehetsgek szles skljt nyjtja a fejleszteszkznk. Konverzikkal kapcsolatban kt esetet szoktak megklnbztetni. Ezek kzl az els szm szvegg alaktsa. Ez gyakorlatilag nem ignyel semmilyen segtsget, a szmtpushoz tartoz osztly ToString fggvnyt hvja meg a fordt. Ehhez nem kell semmit sem tenni. Plda:
int a=2; string s="Az eredmny:" + a;
A msik eset, mikor szvegbl szeretnnk szmot kapni, mr nem ilyen automatikus, de semmikppen nem lehet bonyolultnak nevezni. Tbbfle mdszer lehet az alaktsra, de a legltalnosabb taln a Convert osztly hasznlata. Az osztly konvertl fggvnyei azonos nvkonvencival az albbi formjak:
Convert.ToCTStpusnv
ahol a CTS (Common Type System) tpusnv az albbi lehet: Boolean, Int16 (short int), Int32 (rendes int), Int64 (hossz int), Float, Double, String, Decimal, Byte, Char. Plda:
string s="25"; int i=Convert.ToInt32(s); // i=25 lesz
rdekessgknt megemltem, hogy ltezik a Convert.ToDateTime(object) fggvny is, ami egy knyvtri dtumtpust kszt a paramterl kapott objektumbl. Ha brmelyik konvertl fggvny hibs paramtert kap, nem tud eredmnyt produklni, akkor InvalidCastException kivtelt vagy ms, a hiba okra utal kivtelt generl. A kivtelkezelsrl ksbb rszletesen is fogunk beszlni.
III. Kifejezsek, mveletek ltalban igaz, hogy grafikus alkalmazsok sorn a bert adataink szvegesek, gy minden esetben az azokkal trtn szmols eltt konvertlnunk kell, ezrt a konvertl fggvnyek hasznlata elg gyakori. Hasonl konvertl szolgltatsokat kapunk, ha az alaptpusok Parse fggvnyt hasznljuk (int.Parse(szveg), double.Parse(szveg)). Gyakran elfordul, hogy az alapmveletek nem elgtik ki a szmolsi ignyeinket. A System nvtr Math osztlya a leggyakrabban hasznlt szmolsi mveleteket biztostja. A leggyakrabban hasznlt fggvnyek a kvetkezk: Math.Sin(x) Math.Cos(x) Math.Tan(x) Math.Exp(x) Math.Log(x) Math.Sqrt(x) Math.Abs(x) Math.Round(x) Math.Ceiling(x) Math.Floor(x) Math.Pow(x,y) Math.PI Math.E Plda:
double dd=Math.Sin(Math.PI/2); Console.WriteLine(dd); // rtke 1. dd=Math.Pow(2,3); Console.WriteLine(dd); // 8
sin(x), ahol az x szg rtkt radinban kell megadni cos(x) tg(x) ex ln(x) x ngyzetgyke x abszolt rtke kerekts a matematikai szablyok szerint felfel kerekts lefel kerekts hatvnyozs, xy a PI konstans (3.14159265358979323846) az e konstans (2.7182818284590452354)
Matematikai, statisztikai feladatoknl a vletlenszmok hasznlata gyakori igny. A System nvtr Random osztlya nyjtja a pszeudo-vletlenszmok generlsnak lehetsgt. Egy vletlenszm-objektum ltrehozst a rendszeridhz (paramter nlkli konstruktor) vagy egy adott egsz szmhoz kthetjk. A vletlenobjektum Next fggvnye a kvetkez vletlen egsz szmot, a NextDouble a kvetkez vals vletlenszmot adja. A Next fggvnynek hrom, mg a NextDouble fggvnynek egy vltozata van, amit a kvetkez plda is bemutat.
III.5. Feladatok
1. Mit neveznk ktoperandus opertornak? 2. Melyik opertor hrom operandus? 3. Milyen szm-szveg konverzis lehetsgeket ismer? 4. Fogalmazza meg kt elem kzl a nagyobb kivlasztst operator segtsgvel! 5. Ismerjk egy hromszg kt oldalt s kzbezrt szgt. Szmoljuk ki a szggel szemkzti oldal hosszt!
47
IV. sszetett adattpusok Mivel a nyelv minden dinamikus referencia tpusnak memriabeli felszabadtst a rendszer automatikusan vgzi ezt az irodalom gyakran szemtgyjtsi algoritmusnak (garbage collection) nevezi , ezrt a pldabeli 10 elem vektor memriahelyt automatikusan visszakapja az opercis rendszer. A vektorelemek a fenti dinamikus ltrehozs utn 0 kezdrtket kapnak. Ha egyb elemekkel szeretnnk az inicializcit elvgezni, kapcsos zrjelek kz rva adhatjuk meg azokat. tpus[] nv={rtk, rtk,}; Plda:
int[] n={3,4,5,6}; int hossz= n.Length; // vektorhossz meghatrozs
Ha logikai vektort definilunk, akkor a vektorelemek kezdrtkads hinyban logikai hamis (false), mg ha referencia vektort definilunk, akkor a referenciaelemek a null kezdrtket kapjk meg. Plda:
int[] numbers = {1, 2, 3, 4, 5}; int[] numbers = new int[5] {1, 2, 3, 4, 5}; string[] nevek = new string[3] {"Ali", "Pali", "Robi"}; int[] numbers = new int[] {1, 2, 3, 4, 5}; string[] nevek = new string[] {"Ali", "Pali", "Robi"};
A C# nyelvben nem csak a fenti egydimenzis vektor definilhat. Ezenkvl mg definilhat kt- vagy tbbindex, multidimenzis vektor, illetve vektorok vektora.
Multidimenzis vektor:
Plda:
string[,] nevek; nevek= new string[2,4];
Hasznlat:
numbers[1,1] = 667;
Vektorok vektora:
A ms nyelvekbeli analgit tekintve, a multidimenzis vektorban minden sorban azonos darabszm elem van, ez teht a szablyos, ngyzetes mtrix stb. defincinak felel meg. A vektorok vektora pedig valjban egy mutat vektor definci, ahol elszr megmondjuk, hogy hny elem a mutat vektor, majd ezutn egyenknt meghatrozzuk, hogy az egyes elemek milyen vektorokat jelentenek. Plda:
byte[][] meres = new byte[5][]; for (int x = 0; x < meres.Length; x++) { meres[x] = new byte[4]; } int[][] szamok= new int[2][] { new int[] {3,2,4}, // ez a hrom elem vektor lesz a szamok els vektora new int[] {5,6} // ez a kt elem vektor lesz a szamok msodik vektora }; int[][] numbers = new int[][] { new int[] {2,3,4}, new int[] {5,6,7,8,9} }; int[][] numbers = { new int[] {2,3,4}, new int[] {5,6,7,8,9} };
Termszetesen mindkt esetben multidimenzis, vektorok vektora nem csak ktdimenzis esetrl beszlhetnk, hanem tetszleges mret vektorrl. Plda:
int[,,] harom = new int[4,5,3];
Lehetsgnk van a ktfle vektordefinci kevert hasznlatra is. A kvetkez plda egy olyan egyszer vektort definil, aminek minden eleme 32 dimenzis szablyos mtrix. Plda:
int[][,,][,] mix;
Ezek utn rjunk egy pldaprogramot, amely bemutatja a korbban megbeszlt vektorjellemzk hasznlatt: Plda:
//vektor.cs using System; class vektorpelda { public static void Main() { // Sima vektordefinci, a definci pillanatban // 5 elem vektor lesz // A vektorelemeknek kln nem adtunk kezdrtket, // ezrt azok 0 rtket kapnak. int[] numbers = new int[5]; // Ktdimenzis vektor, sima 5x4-es szveges, //ezen elemek inicializls hinyban null rtket kapnak. string[,] names = new string[5,4]; // Vektorok vektora, ezt az irodalom gyakran //"jagged array", (csipks, szaggatott vektor) nven emlti byte[][] scores = new byte[5][]; // Az egyes vektorok definilsa for (int i = 0; i < scores.Length; i++) { scores[i] = new byte[i+3]; // elemrl elemre n az elemszm. } // Egyes sorok hossznak kirsa
Plda:
string honapnev(int n) { string[]nv={"Nem ltezik","Janur", "Februr","Mrcius", "prilis","Mjus","Jnius", "Jlius","Augusztus", "Szeptember","Oktber", "November","December"}; return(((n<1)||(n>12)) ? nv[0] : nv[n]); }
IV.2. Struktra
Gyakran szksgnk van az eddigiektl eltr adatszerkezetekre, amikor a lerni kvnt adatunkat nem tudjuk egy egyszer vltozval jellemezni. Elg, ha a taln legkzenfekvbb feladatot tekintjk: hogyan tudjuk a sk egy pontjt megadni? Egy lehetsges megadsi md, ha a pontot mint a sk egy derkszg koordintarendszernek pontjt tekintem, s megadom az X s Y koordintkat. A struktradefinils az ilyen feladatok megoldsa esetn lehetv teszi, hogy az sszetartoz adatokat egy egysgknt tudjuk kezelni. A struktradefinci formja a kvetkez:
IV. sszetett adattpusok struct nv { hozzfrs tpus meznevek; hozzfrs fggvnydefinci ; }; Hivatkozs egy mezre: vltoznv.meznv A struktrkon azonos tpus esetn az rtkads elvgezhet, gy ha pldul a s b azonos tpus struktra, akkor az a=b rtkads szablyos, s az a minden mezje felveszi b megfelel mezrtkeit. Plda:
struct pont { int x; int y; }; pont a; struct egy { string name; int kor; }; egy[] c=new egy[10];
A fenti definci teljesen j, csak a hozzfrsi szint megadsnak hinyban minden mez privt, azaz a struktra mindkt adata csak bellrl lthat. A struktra alaprtelmezett mezhozzfrse privt (private). Minden taghoz kln meg kell adni a hozzfrsi szintet. Struktra esetn a megengedett hozzfrsi szintek: private public internal Plda:
struct szemly { public string nv;
csak struktrn bellrl rhet el brki elrheti ezt a mezt programon bellrl (assembly) elrhet
Struktradefinci esetn a nyelv nem csak adatmez, hanem fggvnymez definilst is megenged. Azt a fggvnymezt, aminek ugyanaz a neve, mint a struktrnak, konstruktornak nevezzk. Paramter nlkli konstruktor nem definilhat, azt mindig a krnyezet biztostja. A struktra rtktpus adat, gy a vermen s nem a dinamikus memriban jn ltre. ltalban elmondhat, hogy a struktra majdnem gy viselkedik, mint egy osztly, de funkcionalitst tekintve megmarad a klnbz tpus adatok trolsnl. A struktrkkal kapcsolatosan rdemes megjegyezni hrom alapvet tulajdonsgot: Egy struktra adatmezt a definils pillanatban nem inicializlhatunk.
struct alma { string nev="jonatn"; // fordtsi hiba }
Plda:
Struktra adatmezket a default konstruktor nem inicializl. A kezdrtk belltsrl, ha szksges, sajt konstruktorral vagy egyb belltsi mddal kell gondoskodni. Plda:
struct pont { public int x,y; } pont p=new pont(); p.x=2; p.y=4;
Br a struktra rtk tpus, azrt a new opertorral kell biztostani a sajt konstruktorral trtn inicializcit. Ez ebben az esetben a vermen fog elhelyezkedni.
IV. sszetett adattpusok Befejezsl a struktra definilsra, hasznlatra, struktra vektorra nzznk egy teljesebb pldt: Plda:
using System; struct struktra_plda { public int kor; public string nv; } class struktra_hasznl { public static void Main() { struktra_plda sp=new struktra_plda(); sp.kor=5; sp.nv="va"; // struktra_plda vektor struktra_plda [] spv=new struktra_plda[5]; int i=0; // beolvass while(i<5) { spv[i]=new struktra_plda(); Console.WriteLine("Krem az {0}. elem nevt!",i); string n=Console.ReadLine(); spv[i].nv=n; Console.WriteLine("Krem az {0}. elem kort!",i); n=Console.ReadLine(); spv[i].kor=Convert.ToInt32(n); i++; } // kirs for(i=0;i<5;i++) { Console.WriteLine(spv[i].nv); Console.WriteLine(spv[i].kor); } } }
IV.3. Feladatok
1. Mit neveznk tmbnek?
IV. sszetett adattpusok 2. Milyen tmbk ltrehozst tmogatja a C# nyelv? 3. Mi a klnbsg a tmb s a struktra kztt? 4. Hatrozzuk meg egy tmb legnagyobb elemt! 5. brzoljuk struktra tpussal az alma legjellemzbb adatait (nv, szn, mret)! Ksztsnk 5 elem alma vektort!
V. Utastsok
A programvezrls menett az utastsok szekvencija szabja meg. Ahogy korbban is lttuk, az opercis rendszer a Main fggvnynek adja t a vezrlst, majd a fggvnytrzs egyms utn kvetkez utastsait (szekvencia) hajtja vgre, ezutn tr vissza a vezrls az opercis rendszerhez. Az utastsok fajti: sszetett utasts kifejezs utasts elgazs utasts ciklus utasts ugr utasts
56
V. Utastsok
Ha az igaz gon sszetett utastst hasznlunk, akkor utna pontosvessz nem kell, illetve ha mgis van, az az if lezrst jelenten, s hibs lenne az utastsunk az if nlkli else hasznlata miatt. Plda:
if (c=='a') { Console.WriteLine("Ez az a bet");} else Console.WriteLine("Nem az a bet");
switch (kifejezs) { case rtk1: utasts1 ; case rtk2: utasts2 ; default: utasts ; };
V. Utastsok A switch utni kifejezs nem csak egsz rtk lehet, hanem szveg (string) is. Ha a kifejezs rtke a case utn megadott rtkkel nem egyezik meg, akkor a kvetkez case utni rtk vizsglata kvetkezik. Ha egy case utni rtk azonos a kifejezs rtkvel, akkor az ez utni utasts vgrehajtdik. Ha egy case gban nincs egyrtelm utasts arra vonatkozan, hogy hol folytatdjon a vezrls, akkor fordtsi hibt kapunk. A C++ nyelvet ismerk tudhatjk, hogy abban a nyelvben egy case g vgt nem kellett vezrlstadssal befejezni, s ebbl gyakran addtak hibk. Minden elgazsgat, mg a default gat is, ktelez valamilyen vezrlstadssal befejezni! (break, goto, return) Plda:
switch (parancs) { case "run": Run(); break; case "save": Save(); break; case "quit": Quit(); break; default: Rossz(parancs); break; }
A case belpsi pont utn csak egy rtk adhat meg, intervallum vagy tbb rtk megadsa nem megengedett, hiszen ezek az 'rtkek' gyakorlatilag egy cmke szerept tltik be. Ha kt rtkhez rendeljk ugyanazt a tevkenysget, akkor kt cmkt kell definilni. Plda:
switch (a) { case 1: case 2: Console.WriteLine("Egy s kett esetn"); break; default:Console.WriteLine("Egybknt"); break; };
V. Utastsok
A msodik pldban a ciklusmagban hasznlhattam volna egy utastst is, kihasznlva a ++ opertor postfix alakjt az albbi mdon:
while(i<szveg.Length) Console.WriteLine(szveg[i++]);
V. Utastsok
V.4.2. do utasts
Az utasts formja: do utasts; while (kifejezs) ; A ciklusmag a do s a while kztti rsz vgrehajtsa utn kirtkeli a kifejezst, s amg a kifejezs igaz rtket ad, megismtli a ciklusmag vgrehajtst. A do ciklust szoks htultesztel ciklusnak is nevezni. Plda:
string nv; do { Console.WriteLine("Ki vagy?"); nv=Console.ReadLine(); } while (nv!="Zoli"); Console.WriteLine("Szia {0}!",nv); do Console.WriteLine("Biztos egyszer lefut!"); while(false);
Mindegyik kifejezs elmaradhat. Ha kifejezs2 is elmarad, akkor while (true)-knt tekinti a ciklust. A kifejezsek kztti pontosvessz nem maradhat el. A kifejezs1 tpusdefincs kifejezs utasts is lehet. Nagyon gyakran lthat forrskdban az albbi forma:
V. Utastsok Plda:
for (int i=0; i<10; i++) Console.WriteLine("Hajr Fradi!");
A foreach ciklus az ltalunk definilt vektorokon kvl az ehhez hasonl knyvtri adatszerkezeteken is (ArrayList, Queue stb.) jl hasznlhat. Ezzel kapcsolatos pldt a Helyi knyvtrak hasznlata fejezetben lthatunk. A foreach utasts nemcsak kzvetlen vektortpuson, mint pldul a fenti v vektoron alkalmazhat, hanem minden olyan vgigjrhat tpuson, amely az albbi feltteleknek megfelel: A tpus rendelkezzen egy GetEnumerator() fggvnnyel, aminek eredmnyl kell adni azt a tpust, amilyen tpus elemeken lpdelnk vgig. Definiljunk egy MoveNext() fggvnyt, amelyik az indexet aktulisra lltja, s logikai visszatrssel megadja, hogy van-e mg maradk elem. Definiljunk egy Current tulajdonsgot, ami az aktulis index elemt adja eredmnyl.
V. Utastsok Plda:
using System; public class adatsor { int[] elemek; public adatsor() { elemek = new int[5] {12, 44, 33, 2, 50}; } public vektor GetEnumerator() { return new vektor(this); } // Az "enumerator", class definils: public class vektor { int Index; adatsor a; public vektor(adatsor ad) { a = ad; Index = -1; } public bool MoveNext() { Index++; return(Index < a.elemek.GetLength(0)); } public int Current { get { return(a.elemek[Index]); } } } public class MainClass { public static void Main() { adatsor adatok = new adatsor(); }
V. Utastsok
Console.WriteLine("Az adatsor elemei:"); // elemek kirsa foreach (int i in adatok) { Console.WriteLine(i); }
} } /*Eredmny: 12 44 33 2 50*/
A break a tbbirny elgazs (switch) utastsban is gyakran hasznlt, gy kerlhetjk el, hogy a nem kvnt case gak vgrehajtdjanak.
V. Utastsok Hatsra a legbels while, for, do ciklus utastsokat vezrl kifejezsek kerlnek kirtkelsre. (A ciklus a kvetkez ciklusmag vgrehajtshoz kszl.) Plda:
int i=1; while(true) { i++; if (i<=10) continue; // 10 elem ciklus // kvetkez ciklusmag
A fenti pldban a continue utasts miatt a Console.WriteLine(i) utasts egyszer sem hajtdik vgre.
V. Utastsok
goto case 1; case 1: egy(); goto default; default: valami(); break;
A goto utastsrl zrskppen meg kell jegyezni, hogy a strukturlt programksztsnek nem felttlenl rsze ez az utasts, gy hasznlata sem javasolt. A knyv ksbbi pldaprogramjaiban sem fordul el egyszer sem ez az utasts.
A msik eset a using utasts. Egy ideiglenesen hasznlt objektum esetn a using utasts utn a keretrendszer automatikusan meghvja az objektum Dispose metdust. A using utasts alakja a kvetkez: using (objektum) { utastsok;} Plda:
using (Objektumom o = new Objektumom()) { o.ezt_csinald(); }
V. Utastsok Ez a hasznlat az albbi kdrszletnek felel meg, a nem ismert nyelvi elemeket ksbb ismertetjk:
Objektumom o = new Objektumom(); try {o.ezt_csinald();} finally { if (o != null) ((IDisposable)o).Dispose(); }
A lock utastsnak, ahogy lttuk, a leggyakrabban hasznlt paramtere a this, ha a vdett vltoz vagy fggvnyutasts nem statikus. (Osztlypldnyok.) Ha statikus vltozkat vagy fggvnyutastsokat szeretnnk biztostani (lockolni), hogy egyszerre csak egy vgrehajtsi szl tudjon hozzfrni, akkor a lock referencinak az osztly tpust kell megadni. Plda:
class adatok { static int szamlalo=0; public void mentes(string s)
V. Utastsok
{ lock(typeof(adatok)) { szamlalo++; Console.WriteLine("Adatments elindul!"); for(int i=0;i<50;i++) { Thread.Sleep(1); Console.Write(s); } Console.WriteLine(""); Console.WriteLine("Adatments {0}.alkalommal befejezdtt!",szamlalo); }
} }
A plda bvebb magyarzata, teljes krnyezetbeli alkalmazsa a IX. rsz Prhuzamos programvgrehajts fejezetben tallhat.
V.6. Feladatok
1. Milyen tpus adat szerint kszthetnk tbbirny (switch) elgazst? 2. Milyen elltesztel s htultesztel ciklusokat hasznlhatunk? 3. Mire hasznlhat a break utasts? 4. rjon rvid programot, amely beolvassa egy focicsapat, adott fordulban szerzett pontszmt (0,1,3) egy egsz tpus vltozba, majd felhasznlva a switch utastst a beolvasott rtk alapjn kirja a kvetkez szvegeket: gyzelem, dntetlen, veresg, hibs adat. 5. rjon programot, amelyik beolvas egy kettvel oszthat, 10 s 100 kz es egsz szmot! (Ha rossz rtket adnak meg, akkor addig folytassa a beolvasst, amg a feltteleknek megfelel szmot nem sikerl megadni!)
VI. Fggvnyek
VI.1. A fggvnyek paramtertadsa
Ha egy fggvnynek adatot adunk t paramterknt, akkor alapveten kt klnbz esetrl beszlhetnk. Egy adat rtk szerint s hivatkozs szerint kerlhet tadsra. Az els esetben valjban az eredeti adatunk rtknek egy msolata kerl a fggvnyhez, mg a msodik esetben az adat cme kerl tadsra.
Az gy megvalstott paramtertadst rtk szerinti paramtertadsnak nevezzk, a maximum fggvny kt (x s y) paramtere a hvskor megadott kt paramtert kapja rtkl. rtk szerinti paramtertadsnl, hvskor konstans rtk is megadhat. A fggvny hvsnak egy sajtos esete az, mikor egy fggvnyt sajt maga hv meg. Szoks ezt rekurzv fggvnyhvsnak is nevezni. Erre pldaknt nzzk meg a klasszikus faktorilisszmol fggvnyt.
68
class faktor
static int faktorialis(int x) { return (x<=1?1: (x* faktorialis(x-1)); } static void Main() { Console.WriteLine(faktorialis(4)); }
VI. Fggvnyek
Ahogy a fenti pldn is lthat, a vektor paramterknt a referencijval kerl tadsra. Ez rtk szerinti paramtertadst jelent. Ha egy fggvnyben a mutatott rtket (vektorelemet) megvltoztatom, akkor a vltozs a kls, paramterknt tadott vektorban is lthat lesz! A nyelvben a vektor tudja magrl, hogy hny eleme van (Length), ezrt ellenttben a C++ nyelvvel , az elemszmot nem kell tadni. Tmb esetben is alkalmazhatjuk a referencia vagy out paramter tadsnak lehetsgt. Ennek illusztrlsra nzzk a kvetkez pldkat: 1. plda:
using System; class teszt { static public void feltlt(out int[] vektor) { // a vektor ltrehozsa, s inicializlsa vektor = new int[5] {1, 2, 3, 4, 5}; } static public void Main() { int[] vektor; // nem inicializltuk // meghvjuk a feltlt fggvnyt: feltlt(out vektor); // A vektorelemek kirsa: Console.WriteLine("Az elemek:"); for (int i=0; i < vektor.Length; i++) Console.WriteLine(vektor[i]); } }
VI. Fggvnyek A parancssor-argumentumok hasznlatra nzzk az imnt mr emltett echo parancs egy lehetsges megvalstst. Plda:
static void Main(string[] args) { int i=0; while (i<args.Length) { Console.WriteLine(args[i]); i++; } }
Ha a fenti programot lefordtjuk, s a neve parancs.exe lesz, akkor a kvetkezkppen prblhatjuk ki:
c:\parancs.exe fradi vasas jpest
A parancssori paramterek Visual Studio.NET krnyezetet hasznlva a projekt Tulajdonsg ablakban is megadhatk: Configuration Properties \ Debugging \ Command Line Arguments, ahogy az albbi kpen is lthat.
9. bra
VI. Fggvnyek A Main fggvnyt, abban az esetben, ha a parancssori paramtereket nem akarjuk feldolgozni, a paramterei nlkl is deklarlhatjuk: static void Main()
{}
Egy vltoz paramterszm fggvnynek lehetnek fixen megadott paramterei is. A fixen megadott paramtereknek ktelezen meg kell elznik a vltoz paramtereket. A kvetkez plda egy ilyen fggvnydefincit mutat. Plda:
using System class parameters { public static void valtozo(int x, params object[] list) { Console.WriteLine(x); foreach (object o in list) Console.WriteLine(o); } public static void Main() { valtozo(25, "alma", "barack","szilva"); } }
VI. Fggvnyek Hatrozzuk meg kt szm maximumt! Ha el szeretnnk kerlni a tpuskonvertlst mondjuk egsz tpusrl valsba s fordtva, akkor kln az egsz s kln a vals szmok esetre is meg kell rnunk a maximum fggvnyt. Knyelmetlen dolog lenne, ha mondjuk egszmax s valsmax nven kellene megrni a kt fggvnyt. Mindkt esetben szeretnnk a maximum fggvnynevet hasznlni, hogy ne neknk kelljen eldnteni azt, hogy az egszek vagy valsak maximumt akarjuk-e meghatrozni, hanem dntse el a fordt a paramterlista alapjn automatikusan, hogy melyik fggvnyt is kell az adott esetben meghvni. Plda:
// vals maximum fggvny double maximum(double x,double y) { if (x>y) return x; else return y; } // egsz maximum fggvny int maximum(int x,int y) { if (x>y) return x; else return y; } int a=2,b=4; double c=3.123, d=2; Console.WriteLine(maximum(4.1,2)); Console.WriteLine(maximum(4,2)); Console.WriteLine(maximum(a,b)); Console.WriteLine(maximum(c,d));
Meg kell jegyezni, hogy ezt a tulajdonsgot sok nyelvben fggvnysablon (template) tulajdonsg segtsgvel elegnsabban oldhatnnk meg, de a jelenlegi C# ezt nem tmogatja.
VI. Fggvnyek
Az elbbi pldban teht a pelda deleglt tpust definiltuk. Ez olyan fggvnytpus, amelyiknek egy egsz s egy szveg paramtere van, s eredmnyl egy egsz szmot ad. Egy deleglt objektumnak vagy egy osztly statikus fggvnyt, vagy egy osztly pldnyfggvnyt adjuk rtkl. Deleglt meghvsnl a hagyomnyos fggvnyhvsi formt hasznljuk. Ezek utn nzznk egy konkrt pldt: Plda:
using System; class proba { public static int negyzet(int i) { return i*i; } public int dupla(int i) { return 2*i; } }
VI. Fggvnyek
class foprogram { delegate int emel(int k); // az emel deleglt definilsa public static void Main() { emel f=new emel(proba.negyzet); // statikus fggvny lesz a deleglt Console.WriteLine(f(5)); // eredmny: 25 proba p=new proba(); emel g=new emel(p.dupla); // norml fggvny lesz a deleglt Console.WriteLine(g(5)); // eredmny: 10 }
A delegltakat a krnyezet kt csoportba sorolja. Ha a deleglt visszatrsi tpusa void, akkor egy deleglt tbb vgrehajtand fggvnyt tartalmazhat (multicast, sszetett deleglt), ha nem void a visszatrsi tpus, mint a fenti pldban, akkor egy deleglt csak egy vgrehajtand fggvnyt tud meghvni (single cast, egyszer deleglt). Az egyszer s sszetett delegltakra nzzk a kvetkez pldt: Plda:
using System; class proba { public static int negyzet(int i) { return i*i; } public int dupla(int i) { return 2*i; } public int tripla(int i) { return 3*i; } public void egy(int i) { Console.WriteLine(i); } public void ketto(int i) { Console.WriteLine(2*i); } }
VI. Fggvnyek
class foprogram { delegate int emel(int k); delegate void meghiv(int j); public static void Main() { emel f=new emel(proba.negyzet); Console.WriteLine(f(5)); proba p=new proba(); emel g=new emel(p.dupla); Console.WriteLine(g(5)); emel h=new emel(p.tripla); g+=h; //g single cast, g a tripla lesz Console.WriteLine(g(5)); // eredmny: 15 meghiv m=new meghiv(p.egy); // multicast deleglt m+=new meghiv(p.ketto); m(5); // deleglt hvs, eredmny 5,10 } }
Ha fggvnymutat tpust (deleglt) deklarlunk, akkor rtkads esetn a mutat tpusa hatrozza meg, hogy a fordtnak melyik aktulis fggvnyt is kell az azonos nevek kzl vlasztania.
delegate double vmut(double,double); // vmut olyan deleglt amelyik egy vals rtket visszaad, // s kt vals paramtert vr fggvnyt jelent delegate int emut(int,int); // emut olyan deleglt, amelyik egy egsz rtket visszaad // , s kt egsz paramtert vr fggvnyt jelent vmut mut=new vmut(maximum);// vals hvs Console.WriteLine(mut(3,5));
A multicast deleglt (tpus) definilsi lehetsget, igaztva az ignyeket az esemnyvezrelt programozsi krnyezethez (mind a Windows, mind az X11 ilyen), az egyes objektumokhoz, tpushoz gy kapcsolhatjuk, hogy esemny tpus mezt adunk hozzjuk. Ezt az albbi formban tehetjk meg: public event meghiv esemeny; ahol a meghiv sszetett deleglt. Az esemny objektum kezd rtke null lesz, gy az automatikus meghvs (esemeny()) nem ajnlott!
VI. Fggvnyek Az esemnyhez zrskppen meg kell jegyezni, hogy az egsz keretrendszer a felhasznli tevkenysget ehhez a lehetsghez rendeli akkor, amikor klasszikus Windows alkalmazst akarunk kszteni. Pldaknt nzzk meg egy Windows alkalmazs esetn a form tervez ltal generlt kdot. A form (this) objektuma egy vlasztmez (ComboBox), ampl nvre hallgat. Ennek knyvtri esemnye, a SelectedIndexChanged vgrehajtdik (a keretrendszer hajtja vgre), ha mdostunk a vlasztson. Mikor ehhez az esemnyhez egy esemnykezel fggvnyt definilunk ampl_SelectedIndexChanged nven, akkor az albbi sort adja a programhoz a tervez: Plda:
this.ampl.SelectedIndexChanged += new System.EventHandler(this.ampl_SelectedIndexChanged);
VI.6. Feladatok
1. Milyen paramtertadsi mdokat ismer? 2. Mikor definilhatunk azonos nvvel fggvnyeket egy osztlyban? 3. Hogyan kell vltoz paramterszm fggvnyt hasznlni? 4. rjon egy fggvnyt, amely a paramterknt megadott nhny nv kzl a leghosszabb hosszat adja meg! 5. Definiljon kupafordul esemnyt, melyekre a szurkolk jelentkezhetnek. Kupafordul esetn hvjuk meg a feliratkozott szurkolkat a mrkzsre!
VII. Osztlyok
C#-ban az osztlyok a mr ismert sszetett adatszerkezetek (struktrk) egy termszetes kiterjesztse. Az osztlyok nemcsak adattagokat, hanem opertorokat, fggvnyeket is tartalmazhatnak. Az osztlyok hasznlata esetn ltalban az adatmezk az osztly ltal ppen lerni kvnt esemny llapotjelzi, mg a fggvnymezk az llapotvltozsokat rjk le, felhasznli felletet biztostanak. A fggvnymezket gyakran metdusoknak is nevezi a szakirodalom. Osztlymezket lehetsgnk van zrtt nyilvntani (encapsulation), ezzel biztostva az osztly bels harmnijt. Ezek az osztlymezk ltalban az llapotjelz adatmezk. j ignyek, mdostsok esetn lehetsgnk van az eredeti osztly megtartsa mellett, abbl a tulajdonsgok megrzsvel egy j osztly szrmaztatsra, amely rkli (inheritance) az sosztly tulajdonsgait (az osztlyok elemeit). A C++ nyelvben lehetsgnk van arra, hogy tbb osztlybl szrmaztassunk utdosztlyt (multiple inheritance), esetnkben ezt a jellemzt a CLR nem tmogatja, gy ennek a fejlesztkrnyezetnek egyik nyelve sem tmogatja a tbbszrs rkls lehetsgt. Lehetsgnk van interface defincira, amiket egy osztly implementlhat. Egy osztly tbb interface-t is implementlhat. Az rkls lehetsgnek a gyakorlatban legelszr jelentkez haszna taln az, hogy a programunk forrskdja jelentsen cskkenhet. Egy osztlytpus vltozt, az osztly megjelensi alakjt gyakran objektumnak is szoks nevezni. Az osztlyok hasznlathoz nhny jtancsot, a nyelv jobbkz-szablyt a kvetkez pontokban foglalhatjuk ssze. Ezek a tancsok termszetesen nem a nyelv tanulsi idszakra, hanem a ksbbi, a nyelvben trtn programozsi feladatokra vonatkoznak elssorban. Ha egy programelem nll rtelmezssel, feladattal, tulajdonsgokkal rendelkezik, akkor definiljuk ezt az elemet nll osztlyknt. Ha egy programrsz adata nll objektumknt rtelmezhet, akkor definiljuk t a kvnt osztlytpus objektumaknt. Ha kt osztly kzs tulajdonsgokkal rendelkezik, akkor hasznljuk az rkls lehetsgt. ltalban is elmondhat, hogy ha a programokban az osztlyok kzs vonsokkal rendelkeznek, akkor trekedni kell univerzlis bzisosztly ltrehozsra. Gyakran ezt absztrakt bzisosztlynak is nevezzk. Az osztlyok definilsakor kerljk a nyitott (publikus) adatmezk hasznlatt.
81
VII. Osztlyok
A private tagokat csak az adott osztlyon bellrl rhetjk el. Az osztlyok publikus mezit brhonnan elrhetjk, mdosthatjuk. A protected mezk az osztlyon kvliek szmra nem elrhetek, mg az utdosztlybl igen. Az internal mezket a kszl program osztlyaibl rhetjk el. A protected internal elrs valjban egy egyszer vagy kapcsolattal megadott hozzfrsi engedly. A mez elrhet a programon bellrl, vagy az osztly utdosztlybl! (Egy osztlybl termszetesen tudunk gy utdosztlyt szrmaztatni, hogy ez nem tartozik az eredeti programhoz.) Ha az osztly definilsakor a struct szt hasznljuk, akkor abban elssorban adatok csoportjt szeretnnk sszefogni, ezrt gyakran tancsknt is olvashatjuk, hogy ha hagyomnyos rtelemben vett struktrt, mint sszetett adatszerkezetet szeretnnk hasznlni, akkor azt struct tpus osztlyknt definiljuk. Az egyes meznevekre val hivatkozs ugyangy trtnik, ahogy korbban a struktrk esetben. Az osztlydefinci alakjnak ismeretben nzznk egy konkrt pldt!
Mivel az x az osztly privt mezje, ezrt definiltunk az osztlyba kt fggvnymezt, amelyek segtsgvel be tudjuk lltani, illetve ki tudjuk olvasni az x rtkt. Ahhoz, hogy ezt a kt fggvnyt az osztlyon kvlrl el tudjuk rni, publikusnak kellett ket deklarlni.
static void Main(){ els a = new els(); // legyen egy a nev els tpus // osztlyunk a.x=4; // hiba!!! x privt mez a.bellt(7); // az x mez rtkt 7-re lltjuk Console.WriteLine(a.kiolvas()); }
Osztlyt egy osztlyon vagy egy fggvnyen bell is definilhatunk, ekkor azt bels vagy loklis osztlynak nevezzk. Termszetesen ennek a loklis osztlynak a lthatsga hasonl, mint a loklis vltozk. Mieltt a statikus mezkrl szlnnk, szt kell ejteni a this mutat szereprl. Ez a mutat minden osztlyhoz, struktrhoz automatikusan ltrejn. Ttelezzk fel, hogy definiltunk egy osztlytpust. A programunk sorn van tbb ilyen tpus objektumunk. Felvetdik a krds, hogy amikor az egyes osztlyfggvnyeket meghvjuk, akkor a fggvny vgrehajtsa sorn honnan tudja meg a fggvnynk, hogy most ppen melyik aktulis osztlyobjektumra is kell, hogy hasson? Minden osztlyhoz automatikusan ltrejn egy mutat, aminek a neve this, s az ppen aktulis osztlyra mutat. gy, ha egy osztlyfggvnyt meghvunk, amely valamilyen mdon pldul a privt vltozkra hat, akkor az a fggvny a this mutatn keresztl tudja, hogy mely aktulis privt mezk is tartoznak az objektumhoz. A this mutat konkrtabb hasznlatra a ksbbiek sorn lthatunk pldt. Ttelezzk fel, hogy egy mreszkzt, egy adatgyjtrendszert egy osztlylyal akarunk jellemezni. Ennek az osztlynak az egyes objektumai a mreszkznk meghatrozott tulajdonsgait kpviselik. Viszont az eszkz jelerstsi egytthati azonosak. Ezrt szeretnnk, hogy az osztly erstsmezje kzs legyen, ne objektumhoz, hanem az osztlyhoz ktdjn. Ezt a lehetsget statikus mezk segtsgvel valsthatjuk meg.
VII. Osztlyok Statikus mezket a static jelz kirsval definilhatunk. Ekkor az adott mez minden objektum esetben kzs lesz. A statikus mez kezdrtke inicializls hinyban 0, null, false lesz. Plda:
class teszt { public static int a; // rtke mg 0 public static string s="Katalin"; }; teszt.a=5; // statikus mez rtkadsa, 5 az rtk
Statikus mezk a this mutatra vonatkoz utalst nem tartalmazhatnak, hiszen a statikus mezk minden egyes objektum esetn (azonos osztlybelire vonatkozan) kzsek. Teht pldul statikus fggvnyek nem statikus mezket nem tudnak elrni! Fordtva termszetesen problmamentes az elrs, hiszen egy norml fggvnybl brmely statikus mez, fggvny elrhet.
10. bra
VII. Osztlyok
class program { public static void Main() { // valahol itt a program elejn kerl meghvsra a // statikus_osztly statikus konstruktora, az x rtke 2 lesz!!! Console.WriteLine(statikus_osztaly.x); // 2 statikus_osztaly s=new statikus_osztaly(); // dinamikus pldny Console.WriteLine(s.getx()); // termszetesen ez is 2 lesz } }
VII. Osztlyok
class program { public static void Main() { // nem lehet nincs_peldanya tpus vltozt definilni Console.WriteLine(nincs_peldanya.x); // 4 // csak a statikus mezket hasznlhatjuk nincs_peldanya.fv1(); } }
A fenti destruktor konstrukcinak egyetlen bizonytalan pontja van, ez pedig a vgrehajts idpontja. Ha szksgnk van olyan megoldsra, ami determinlt destrukcis folyamatot eredmnyez, akkor ezt az n. Dispose metdus implementlsval (ez az IDisposable interface rsze) tehetjk meg. Mieltt ezzel a klasszikus hasznlati formval foglalkoznnk, meg kell ismerkednnk a System nvtr GC osztlynak a szemtgyjtsi algoritmus befolysolsra leggyakrabban hasznlt metdusaival:
void System.GC.Collect();
A hv vgrehajtsi szl addig vrakozik, amg a destruktorok hvsnak sora (Finalize fggvnyek hvsi sora) res nem lesz. Semmi garancia nincs arra, hogy ez a fggvnyhvs visszatr, hiszen ettl a szltl fggetlenl ms objektumok is letciklusuk vgre rhetnek.
void System.GC.SupressFinalize(Object o);
VII. Osztlyok Ha egy objektumnak nincs szksge mr semmilyen destrukcira, Finalize fggvnyhvsra, akkor a paramterl adott objektum ilyen lesz:
void System.GC.ReRegisterForFinalize(Object o);
Mris feliratkozunk a destrukcira vrakozk sorba. Termszetesen, ha ezt tbbszr hvjuk meg, akkor az objektum tbbszr a vrakozk sorba kerl. Ahogy korbban emltettk a destruktorral kapcsolatosan, mi nem tudjuk meghvni, a destruktort a keretrendszer szemtgyjt algoritmusa hvja meg. Ha mgis szksgnk lenne olyan hvsra, amit kzvetlenl is vgre tudunk hajtani, akkor a Dispose fggvny definilsra van szksgnk. Ekkor jellemzen egy logikai vltoz mutatja, hogy az aktulis objektum l, s mg nem hvtk meg a Dispose metdust. Ezen fggvny klasszikus hasznlata a kvetkez:
bool disposed=false; protected void Dispose( bool disposing ) { if( !disposed ) { if (disposing) { // ide jn az erforrs felszabadt kd } this.disposed=true; // nem kell tbb hvs // ha van sosztly, akkor annak dispose hvsa base.Dispose( disposing ); // erre az objektumra mr nem kell finalize fggvnyt //hvni a keretrendszernek GC.SupressFinalize(this); } }
Itt kell szt ejtennk arrl, hogy a nyelv using utastsnak segtsgvel (lsd a Nyelvi utastsok fejezetet) tmr kd rhat. A destrukci folyamata lnyegben a hatkony erforrs-gazdlkodshoz nyjt segtsget. Ennek egyik leglnyegesebb eleme a memriagazdlkods. Br a mai szmtgpek vilgban a memria nagysga nem a kritikus paramterek kztt szerepel, azrt elfordulhat, a fejlesztsek sorn az alkalmazsunk memriahinyban szenved. Ekkor segtsget adhatunk a memria-visszanyer szemtgyjtsi algoritmusnak ahhoz, mely terleteket lehet visszaadni a
VII. Osztlyok rendszer rszre. A kritikus esetben visszaadhat objektumok hivatkozsait gyenge referencinak (weak reference) nevezzk. Ezeket az objektumokat erforrs hinyban a keretrendszer felszabadtja. Ilyen objektumot a WeakReference tpus segtsgvel tudunk ltrehozni. Plda:
Object obj = new Object(); // ers referencia WeakReference wr = new WeakReference(obj); obj = null; // az eredeti ers objektumot megszntetjk // obj = (Object) wr.Target; if (obj != null) {//garbage collection mg nem volt // } else {// objektum trlve // }
A destruktorral kapcsolatban zrskppen a kvetkez (a rendszer szolgltatsaibl ered) tancsokat adhatjuk: Az esetek nagy rszben, ellenttben a C++ nyelvbeli hasznlattal, nincs szksg destruktor definilsra. Ha mgis valamilyen rendszererforrst kzi kddal kell lezrni, akkor definiljunk destruktort. Ennek htrnya az, hogy vgrehajtsa nem determinisztikus. Ha programkdbl kell destruktor jelleg hvst kezdemnyezni, a C++ beli delete hvshoz hasonlan, akkor a Dispose fggvny definilsval, majd annak hvsval lhetnk. A feladataink sorn gyakorta elfordul, hogy egy verem-adatszerkezetet kell ltrehoznunk. Definiljuk most a veremosztlyt gy, hogy a rendszerknyvtr Object tpust tudjuk benne trolni. Ennl a feladatnl is, mint ltalban az igaz, hogy nincs szksgnk destruktor definilsra. Plda:
using System; class verem { Object[] x; int mut; public verem(int db) { x=new object[db]; mut=0; }
// elemek trolsi helye // veremmutat // konstruktor // helyet foglalunk a vektornak // az els szabad helyre mutat
VII. Osztlyok
// NEM DEFINILUNK DESTRUKTORT // MERT AZ AUTOMATIKUS SZEMTGYJTSI // ALGORITMUS FELSZABADTJA A MEMRIT public void push(Object i) { if (mut<x.Length) { x[mut++]=i; } // beillesztettk az elemet } public Object pop() { if (mut>0) return x[--mut]; // ha van elem, akkor visszaadjuk a tetejrl else return null; } } class program { public static void Main() { verem v=new verem(6); v.push(5); v.push("alma"); Console.WriteLine(v.pop());// alma kivtele a verembl // az 5 mg bent marad } }
A kpernyn futsi erdemnyknt az alma szt ltjuk. Egy osztly termszetes mdon nemcsak egyszer adatmezket tartalmazhat, hanem osztlymezket is. A tagosztlyok inicializlsa az osztly definciban vagy a konstruktor fggvnyben explicit kijellhet. Az explicit kijellstl fggetlenl egy objektum inicializlsakor az objektum konstruktornak vgrehajtsa eltt, a tagosztlykonstruktorok is meghvsra kerlnek a deklarci sorrendjben.
VII. Osztlyok
Egy konstans mez elrshez nincs szksg arra, hogy a tpusbl egy vltozt ksztsnk, ugyanis a konstans mezk egyben statikus mezk is. Ahogy lthat, a konstans mezt helyben inicializlni kell, ebbl pedig az kvetkezik, hogy minden ksbb definiland osztlyvltozban ugyanezen kezdrtkads hajtdik vgre, teht ez a mez minden vltozban ugyanaz az rtk lehet. Ez pedig a statikus mez tulajdonsga.
VII. Osztlyok
class olvashatosapp { public static void Main() { csak_olvashato o=new csak_olvashato(5); Console.WriteLine(o.x); // rtke 5 csak_olvashato p=new csak_olvashato(6); Console.WriteLine(p.x); // rtke 6 p.x=8; // fordtsi hiba, x csak olvashat!!!! } }
Termszetesen definilhat egy csak olvashat mez statikusknt is, ebben az esetben a mez inicializlst az osztly statikus konstruktorban vgezhetjk el.
VII. Osztlyok
} set { } return nev;
nev=value;
} class program { public static void Main() { Ember e=new Ember("Zoli", 16); //a Nev tulajdonsg hvsa Console.WriteLine(e.Nev); // a Nev property get blokk hvsa e.Nev="Pali"; // a Nev property set blokkjnak hv// sa a value vltozba kerl a "Pali" } }
Ha a tulajdonsg fggvnynek csak get blokkja van, akkor azt csak olvashat tulajdonsgnak (readonly) nevezzk. Ha a tulajdonsg fggvnynek csak set blokkja van, akkor azt csak rhat tulajdonsgnak (writeonly) nevezzk.
VII. Osztlyok
public int this[int i] { get { return v[i]; } set { v[i]=value; } }
} class program { static void Main() { valami a=new valami(); a[2]=5; // az indexer set blokk hvsa Console.WriteLine(a[2]); // 5, indexer get hvsa } }
Az indexer esetben is, hasonlan a tulajdonsgdefinc hasznlathoz, nem felttlenl kell mindkt (get, set) gat definilni. Ha csak a get blokk definilt, akkor csak olvashat, ha csak a set blokk definilt, akkor csak rhat indexer fggvnyrl beszlnk. Az indexerhasznlat ksrtetiesen hasonlt a vektorhasznlathoz, de van nhny olyan klnbsg, amit rdemes megemlteni. Az indexer fggvny, egy fggvnynek pedig nem csak egsz (index) paramtere lehet. Plda:
public int this[string a, int b] { get { return x; } set { x=value; } }
az indexer fggvny az elzekbl kvetkezen jradefinilhat (overloaded). A fenti indexer mellett a kvetkez hagyomnyos is megfr:
VII. Osztlyok
class program { static int ngyzet(plda a) { a.X=5; return (a.X*a.X); } static void Main() { plda b=new plda(3); Console.WriteLine(ngyzet(b)); } }
Mikor egy fggvny paramterknt (rtk szerint) egy osztlyt kap, akkor a fggvnyparamter egy rtkreferencit kap, s nem egy msolata kszl el az eredeti osztlyvltoznak. Teljesen hasonl akkor a helyzet, mikor egy fggvny osztlytpust ad visszatrsi rtkknt.
VII. Osztlyok Az opertor fggvny defincijnak formja: static visszatrsi_rtk operator?(argumentum) { // fggvnytrzs } Az operator kulcssz utni ? jel helyre az jradefinilni kvnt opertor neve kerl. Teht ha pldul az sszeads (+) opertort szeretnnk fellbrlni, akkor a ? helyre a + jel kerl. Az irodalomban az opertor jradefinilst gyakran opertor overloadingnak hvjk. Az opertorok precedencija jradefinils esetn nem vltozik, s az operandusok szmt nem tudjuk megvltoztatni, azaz pldul nem tudunk olyan / (oszts) opertort definilni, amelynek csak egy operandusa van. Az opertor fggvnyek rkldnek, br a szrmaztatott osztlyban az sosztly opertor fggvnyei igny szerint jradefinilhatak. Az opertor fggvny argumentumval kapcsolatosan elmondhatjuk, hogy egyoperandus opertor esetn egy paramtere van, mg ktoperandus opertor esetn kt paramtere van a fggvnynek. Meg kell emlteni, hogy a C++ nyelvhez kpest nem olyan ltalnos az opertor jradefinils lehetsge, de az is igaz, hogy sok, ma npszer programozsi nyelv (Java, Delphi, ) mg ennyit se nyjt. Tekintsk els pldaknt a komplex szmokat megvalst osztlyt, amelyben az sszeads opertort szeretnnk definilni oly mdon, hogy egy komplex szmhoz hozz tudjunk adni egy egsz szmot. Az egsz szmot a komplex szm vals rszhez adjuk hozz, a kpzetes rsz vltozatlan marad. Plda:
using System; class komplex { private float re,im; public komplex(float x,float y) // konstruktor { re=x; im=y; } float Re { get { return re; }
VII. Osztlyok
set { } float Im { get { } set { } } public static komplex operator+(komplex k,int a) { komplex y=new komplex(0,0); y.Re=a+k.Re; y.Im=k.Im; return y; } override public string ToString() { string s="A keresett szm:"+re+":"+im; return s; } } class program { public static void Main() { komplex k=new komplex(3,2); Console.WriteLine("Komplex szm plda."); Console.WriteLine("sszeads eredmnye: {0}",k+4); } } return im; } re=value;
im=value;
VII. Osztlyok A k+4 sszeads gy rtelmezend, hogy a k objektum + fggvnyt hvtuk meg a k komplex szm s a 4 egsz szm paramterrel, azaz k.+(k,4) fggvnyhvs trtnt. Abban az esetben, ha a komplex + komplex tpus sszeadst szeretnnk definilni, akkor egy jabb opertor fggvnnyel kell a komplex osztlyt bvteni. Ez a fggvny a kvetkezkppen nzhet ki:
public static komplex operator+(komplex a, komplex b) { komplex temp=new komplex(0,0); temp.re= b.re+a.re; temp.im= b.im+a.im; return temp; }
Ahhoz, hogy az sszeads opertort a korbban (az egyszer tpusoknl) megszokott mdon tudjuk itt is hasznlni, mr csak az kell, hogy az egsz + komplex tpus sszeadst is el tudjuk vgezni. (Az sszeads kommutatv!) Erre az eddigi kt sszeads opertor nem ad lehetsget, hiszen ebben az esetben, a bal oldali operandus mindig maga az aktulis osztly. A mostani esetben viszont a bal oldali operandus egy egsz szm. Ekkor a legkzenfekvbb lehetsg az, hogy az egsz + komplex opertorfggvnyt is definiljuk. Figyelembe vve a Visual Studio szvegszerkesztjnek szolgltatsait, ez gyorsan megy, gy elksztjk ezt a vltozatot is:
public static komplex operator+(int a, komplex k) { komplex y=new komplex(0,0); y.Re=a+k.Re; y.Im=k.Im; return y; }
Ekkor a Console.WriteLine("sszeads eredmnye: {0}",4+k); utasts nem okoz fordtsi hibt. Erre a problmra mg egy megoldst adhatunk. Ez pedig a konverzis opertor definilsnak lehetsge. Ugyanis, ha definilunk olyan konverzis opertort, amely a 4 egsz szmot komplex tpusra konvertlja, akkor kt komplex szm sszeadsra vezettk vissza ezt az sszeadst. A konverzis opertoroknak kszthetnk implicit vagy explicit vltozatt is. Implicitnek nevezzk azt a konverzis opertorhvst, mikor nem jelljk a forrsszvegben a konverzi mvelett, explicitnek pedig azt, amikor jelljk.
VII. Osztlyok Konverzis opertornl az opertor jel helyett azt a tpust rjuk le, amire konvertlunk, mg paramterl azt a tpust adjuk meg, amirl konvertlni akarunk. Visszatrve a fenti komplex szm krdsre, az egsz + komplex opertor helyett az albbi opertort is definilhattuk volna:
public static implicit operator komplex(int a) { komplex y=new komplex(0,0); y.Re=a; return y; }
Ha az opertor sz el az implicit kulcsszt rjuk, akkor az implicit opertor fggvnyt definiljuk, teht 4 + komplex jelleg utastsnl a 4 szmot implicit (nem jellve kln) konvertljuk komplex szmm. Elfordulhat, hogy az implicit s az explicit konverzi mst csinl, ekkor, ha akarjuk, az explicit verzit is definilhatjuk.
public static explicit operator komplex(int a) { komplex y=new komplex(0,0); y.Re=a+1; // mst csinl, mint az elz // nem biztos, hogy matematikailag is helyes!!! return y; }
// 6
Termszetesen egy komplex szmhoz rtkads tjn rendelhetnk egy vals szmot is, mondjuk oly mdon, hogy a komplex szm vals rszt adja a vals szm, mg a kpzetes rsz legyen 0. Kt egyoperandus opertor, a ++ s a -- esetben, ahogy az opertorok trgyalsnl is lttuk, ltezik az opertorok postfix illetve prefix formj hasznlata is:
komplex k=new komplex(1,2); k++; // postfix ++ ++k; // prefix forma
VII. Osztlyok Ha definilunk ++ opertor fggvnyt, akkor ezen kt opertor esetben mindkt forma hasznlatnl ugyanaz az opertor fggvny kerl meghvsra.
public static komplex operator++(komplex a) { a.Re=a.Re+1; a.Im=a.Im+1; return a; }
Befejezsl a true, false egyoperandus opertor definilsnak lehetsgrl kell rviden szlni. A C++ nyelvvel ellenttben, ahol egy adott tpust logikainak is tekinthetnk (igaz, ha nem 0, hamis, ha 0), a C# nyelvben a mr korbbrl ismert
if (a) utasts;
alak utastsok akkor fordulnak le, ha az a vltoz logikai. A true s false nyelvi kulcsszavak nemcsak logikai konstansok, hanem olyan logikai egyoperandus opertorok, melyeket jra lehet definilni. A true, false opertor logikai. Megkts, hogy mindkt opertort egyszerre kell jradefinilnunk. A jelentse pedig az, hogy az adott tpust mikor tekinthetjk logikai igaznak vagy hamisnak. Definiljuk jra ezeket az opertorokat a mr megismert komplex osztlyunkhoz:
public static bool operator true(komplex x) { return x.Re > 0; } public static bool operator false(komplex x) { return x.Re <= 0; }
Ez a definci ebben az esetben azt jelenti, hogy egy komplex szm akkor tekinthet logikai igaz rtknek, ha a szm vals rsze pozitv. Plda:
komplex k=new komplex(2,0); if (k) Console.WriteLine("Igaz");
VII. Osztlyok Vgl azt kell megemlteni, hogy a logikai true, false opertorok mintjra, azokhoz hasonlan csak prban lehet jradefinilni nhny opertort. Ezek az opertorok a kvetkezk: ==, != <, > <=, >= azonossg, klnbzsg megadsa kisebb, nagyobb kisebb vagy egyenl, nagyobb vagy egyenl
VII. Osztlyok A fenti pldban definiltuk az Ialma interface-t, ami mg nem jelent kzvetlenl hasznlhat tpust, hanem csak azt rja el, hogy annak a tpusnak, amelyik majd ennek az IAlma tpusnak a tulajdonsgait is magn viseli, ktelezen definilnia kell a nyri(), s a termstlag() fggvnyeket. Teht errl a tpusrl azt tudhatjuk, hogy az interface ltal elrt tulajdonsgokkal biztosan rendelkezni fog. Ezen ktelez tulajdonsgok mellett termszetesen tetszleges egyb jellemzkkel is felruhzhatjuk majd az osztlyunkat. Amikor knyvtri elrsokat, interface-eket implementlunk, akkor ltalban az elnevezsek az I betvel kezddnek, utalva ezzel a nv ltal jelzett tartalomra. Egy interface elrsai kz nem csak fggvnyek, hanem tulajdonsgok s indexer elrs megadsa s esemny megadsa is beletartozhat. Plda:
interface IPozci { int X { get; set; int Y { get; } int Z { set; } int this[int i] { int this[int i] { int this[int i] { }
} // readonly tulajdonsg // csak rhat tulajdonsg get; set;} // read-write indexer get; } // read-only indexer set;} // write-only indexer
VII. Osztlyok
return 230; else return 0; } }
class program { public static void Main() { jonatn j=new jonatn(8); Console.WriteLine(j.termstlag()); // 230 kg az tlagterms } }
VII. Osztlyok
public double termstlag() { return 250; } public string csomagols_mdja() { return "kontner"; } public bool szllt() { return false; } } class program { public static void Main() { jonatn j=new jonatn(); Console.WriteLine(j.termstlag());// 250 kg az tlagterms Console.WriteLine(j.csomagols_mdja()); // kontner } }
A definilt j tpusra vonatkozan hasznlhatjuk mind az is mind az as opertort. Az imnti pldt tekintve rtelmes, s igaz eredmnyt ad az albbi elgazs: Plda:
if (j is IAlma) Console.WriteLine("Ez bizony alma utd.!"); IAlma a=j as IAlma; a.termstlag(); // IAlma tpusra konvertls // fggvnyvgrehajts
VII. Osztlyok Hasonlan az osztlyok mezhozzfrsi rendszerhez, tbb nyelvben is lehetsg van arra, hogy rkls esetn az utdosztly az sosztly egyes mezit tbbfle (private, protected , public) mdon rklheti. A C# nyelvben a .NET Frameworknek (Common Type System) ksznheten erre nincs md. Minden mez automatikusan, mintha publikus rkls lenne, megtartja sosztlybeli jelentst. Ekkor az sosztly publikus mezi az utdosztlyban is publikus mezk, s a protected mezk az utdosztlyban is protected mezk lesznek. Egy stpus referencia brmely utdtpusra hivatkozhat. Az sosztly privt mezi az utdosztlyban is privt mezk maradnak az sosztlyra nzve is, gy az sosztly privt mezi kzvetlenl az utdosztlybl sem rhetk el. Az elrsk pldul publikus, n. kzvett fggvny segtsgvel valsthat meg. Az elrsi mdok gyakorlati jelentst nzzk meg egy sematikus pldn keresztl:
class s { private int i; protected int j; public int k; public void f(int j) { i=j; }; } class utd: s { };
Ekkor az utdosztlynak helybl lesz egy protected mezje, a j egsz vltoz, s lesz kt publikus mezje, a k egsz vltoz s az f fggvny. Osztlyknyvtrak hasznlata mellett (pl. MFC for Windows, Windows NT) gyakran tallkozunk azzal az esettel, mikor a knyvtrosztly protected mezket tartalmaz. Ez azt jelenti, hogy a fggvnyt, mezt olyan hasznlatra szntk, hogy csak szrmaztatott osztlybl tudjuk hasznlni. A C# nyelvben nincs lehetsgnk tbbszrs rkls segtsgvel egyszerre tbb sosztlybl egy utdosztlyt szrmaztatni. Helyette viszont tetszleges szm interface-t implementlhat minden osztly.
class utd: s, interface1, { }; //
VII. Osztlyok Konstruktorok s destruktorok hasznlata rkls esetn is megengedett. Egy tpus definilsakor a konstruktor fggvny kerl meghvsra, s ekkor elszr az sosztly konstruktora, majd utna az utdosztly konstruktora kerl meghvsra, mg destruktor esetn fordtva, elszr az utdosztly majd utna az sosztly destruktort hvja a rendszer. Termszetesen a destruktor hvsra az igaz, hogy a keretrendszer hvja meg valamikor azutn, hogy az objektumok lettartama megsznik. Paramteres konstruktorok esetn az utdkonstruktor alakja:
utd(paramterek): base(paramterek) { } //
Tbbszrs rkls esetn elszr az skonstruktorok kerlnek a definci sorrendjben vgrehajtsra, majd az utdbeli tagosztlyok konstruktorai s legvgl az utdkonstruktor kvetkezik. A destruktorok hvsnak sorrendje a konstruktorsorrendhez kpest fordtott. Ha nincs az utdban direkt shvs, akkor a rendszer a paramter nlkli skonstruktort hvja meg. Ezek utn nzzk a fentieket egy pldn keresztl. Plda:
using System; class a { public a() { Console.WriteLine( "A konstruktor";} ~a() { Console.WriteLine("A destruktor";} } class b: a { public b() { Console.WriteLine("B konstruktor";} ~b() { Console.WriteLine("B destruktor";} } class program { public static void Main() { b x=new b(); // b tpus objektum keletkezik, majd 'kimlik' // Elszr az a majd utna a b konstruktort hvja meg // a fordt
VII. Osztlyok
// Kimlskor fordtva, elszr a b majd az a // destruktora kerl meghvsra } }
Ha protected mezt definilunk egy sealed osztlyban, akkor a fordt figyelmeztet zenetet ad, mivel nincs sok rtelme az utdosztlyban lthat mezt definilni. Interface definils esetben csak elrsokat fggvny, tulajdonsg formban fogalmazhatunk meg az implementl osztly szmra. Gyakran elfordul, hogy olyan tpust szeretnnk ltrehozni, mikor a definilt tpusbl mg nem tudunk pldnyt kszteni, de nemcsak elrsokat, hanem adatmezket, implementlt fggvnyeket is tartalmaz. Ez a lehetsg az abstract osztly definilsval valsthat meg. Ehhez az abstract kulcsszt kell hasznlnunk az osztly neve eltt. Egy absztrakt osztly egy vagy tbb absztrakt fggvnymezt tartalmazhat (nem ktelez!!!). Ilyen fggvnynek nincs trzse, mint az interface fggvnyeknek. Egy absztrakt osztly utdosztlyban az absztrakt fggvnyt ktelez implementlni. Az utdosztlyban ekkor az override kulcsszt kell a fggvny fejlcbe rni.
az osztlynak nincs absztrakt mezje, de ettl az osztly mg lehet absztrakt hiba, mert absztrakt osztlybl nem kszthetnk vltozt
2. plda:
using System; abstract class os { private int e; public os(int i) { e=i; } public abstract int szamol(); public int E { get { return e; } } } class szamolo:os { public szamolo():base(3) { } public override int szamol() { return base.E*base.E; } }
VII. Osztlyok
class program { public static void Main() { szamolo f=new szamolo(); Console.WriteLine(f.szamol()); // eredmny: 9 } }
VII. Osztlyok
class kor:pont { private int r; public kor() { r=5; } public void kiir() { Console.WriteLine(r); } } class program { public static void Main() { kor k=new kor(); pont p=new pont(); p.kiir(); //2,1 k.kiir(); //5 } }
A program futsnak eredmnyeknt elszr a p pont adatai (2,1), majd a kor adata (5) kerl kirsra. Bvtsk a programunkat az albbi kt sorral:
public static void Main() { kor k=new kor(); pont p=new pont(); p.kiir(); k.kiir(); p=k; //Egy stpus egy utdra hivatkozik p.kiir(); //Mit r ki? }
A p=k rtkads helyes, hiszen p (pont tpus) tpusa a k tpusnak (kor) az se. Azt is szoktuk mondani, hogy egy stpus referencia tetszleges utdtpusra hivatkozhat. Ekkor a msodik p.kiir() utasts is, a p=k rtkadstl fggetlenl a 2,1 rtkeket rja ki! Mirt? Mert az osztlyreferencik alaprtelmezsben statikus hivatkozsokat tartalmaznak a sajt fggvnyeikre. Mivel a pontban van kiir, ezrt attl fggetlenl, hogy idkzben a program sorn (futs kzbeni dinamikus mdosts utn) a p mr egy kr objektumot azonost, azaz a kr kiir fggvnyt kellene meghvni, mg mindig a fixen, fordtsi idben hozzkapcsolt pont.kiir fggvnyt hajtja vgre.
VII. Osztlyok Ha azt szeretnnk elrni, hogy mindig a dinamikusan hozztartoz fggvnyt hvja meg, akkor az sosztly fggvnyt virtulisnak (virtual), mg az utdosztly fggvnyt felldefiniltnak (override) kell nevezni, ahogy az albbi plda is mutatja. Plda:
using System; class pont { private int x,y; public pont() { x=2;y=1; } virtual public void kiir() { Console.WriteLine(x); Console.WriteLine(y); } } class kor:pont { private int r; public kor() { r=5; } override public void kiir() { Console.WriteLine(r); } } public class MainClass { public static void Main() { kor k=new kor(); pont p=new pont(); p.kiir(); // pont kiir2,1 k.kiir(); // kor kiir 5 p=k; // a pont a korre hivatkozik p.kiir(); // kor kiir 5 a kor kiir kerl // meghvsra, mert a kiir fggvny virtulis, gy a // kiir hvsakor mindig a vltoz aktulis, s nem // pedig az eredeti tpust kell figyelembe venni. } }
VII. Osztlyok Ez a tulajdonsg az osztlyszerkezet rugalmas bvtst teszi lehetv, mg a programkd bonyolultsga jelentsen cskken. Gyakran elfordul, hogy az sosztlyban nincs szksgnk egy fggvnyre, mg a szrmaztatott osztlyokban mr igen, s szeretnnk, ha virtulisknt tudnnk definilni. Ebben az esetben az sosztlyban egy absztrakt fggvnydefincit kell hasznlnunk, ahogy az albbi pldban olvashat. Plda:
abstract class pont // absztrakt osztly, ebbl nem { // lehet pldnyt kszteni protected int x,y; public pont() { x=20;y=10; } abstract public void rajzol(); public void mozgat(int dx, int dy) { x+=dx; y+=dy; // rajzol hvs rajzol(); } } class kor:pont { private int r; public kor() { r=5; } override public void rajzol() { Console.WriteLine("Megrajzoljuk a krt az {0}, {1} pontba, {2} sugrral.",x,y,r); } } public class MainClass { public static void Main() { // pont p=new pont(); utastshibt eredmnyezne kor k=new kor(); k.mozgat(3,4); } }
VII. Osztlyok
class focicsapat
protected string csapat; public focicsapat() { csapat="UTE"; } public void nevkiir() { Console.WriteLine("Kedves csapat a lila-fehr {0}",csapat); }
} class kedvenc_csapat:focicsapat { public kedvenc_csapat() { csapat="Fradi"; } new public void nevkiir() { Console.WriteLine("Kedvenc csapatunk a: {0}",csapat); } } public class MainClass { public static void Main() { kedvenc_csapat cs=new kedvenc_csapat(); cs.nevkiir(); } }
A new utasts hatsra egy rklsi sor j bzisfggvnye lesz az gy definilt nevkiir fggvny. Ennek az ellenkezjre is igny lehet, mikor azt akarjuk elrni, hogy az sosztly fggvnyt semmilyen ms formban ne lehessen megjelenteni. Ekkor a fggvnyt, az osztly mintjra, vglegesteni kell, azaz a sealed jelzvel kell megjellni.
VII. Osztlyok
VII.11. Feladatok
1. Mi a klnbsg egy struktra s egy osztly kztt? 2. Milyen szerepe van a konstruktoroknak, destruktoroknak? Milyen konstruktorok definilhatk? 3. Mi a klnbsg az osztly, az absztrakt osztly is az interface kztt? 4. Definiljon btor osztlyt a jellemz tulajdonsgokkal! (Btor neve, alapanyaga, rendeltetse, ra) A megadott tulajdonsgokhoz ksztse el a kezel fggvnyeket! Ksztsen lapraszerelt nvvel interface-t, amiben az sszeszerelsi utastst rjuk el! Mdostsa az elz btor osztlyt lapraszerelt btorra, amelyik implementlja a lapraszerelt interface-t, biztostva azt, hogy ennek a tpusnak biztosan legyen sszeszerelsi utastsa.
VIII. Kivtelkezels
Egy program, programrsz vagy fggvny vgrehajtsa formlis eredmnyessg tekintetben hrom kategriba sorolhat. A fggvny vagy programrsz vgrahajtsa sorn semmilyen rendellenessg nem lp fel. A fggvny vagy programrsz aktulis hvsa nem teljesti a paramterekre vonatkoz elrsainkat, gy ekkor a sajt hibavdelmnk eredmnyeknti hibval fejezdik be a vgrehajts. A fggvny vagy programrsz vgrehajtsa sorn elre nem lthat hibajelensg lp fel. Ezen harmadik esetben fellp hibajelensgek programban trtn kezelsre nyjt lehetsget a kivtelkezels (Exception handling) megvalstsa. Ha a msodik esetet tekintjk, akkor a sajt hibavdelmnk segtsgvel, mondjuk valamilyen nem hasznlt visszatrsi rtkkel tudjuk a hv fl tudomsra hozni, hogy hiba trtnt. Ez nha komoly problmkat tud okozni, hiszen pldul egy egsz rtkkel visszatr fggvny esetben nha elg krlmnyes olyan egsz rtket tallni, amelyik nem egy lehetsges valdi visszatrsi rtk. gy ebben az esetben is, br a fellp hibajelensg valahogy kezelhet, a kivtelkezels lehetsge nyjt elegns megoldst. A kivtelkezels lehetsge hasonl, mint a fordtsi idben trtn hibakeress, hibavdelem azzal a klnbsggel, hogy mindezt futsi idben lehet biztostani. A C# kivtelkezels a hibakezelst tmogatja. Nem tmogatja az n. aszinkron kivtelek kezelst, mint pldul billentyzet- vagy egyb hardvermegszakts (interrupt) kezelse. Ehhez hasonl lehetsggel mr a BASIC nyelvben is tallkozhattunk (ON ERROR GOTO, ON ERROR GOSUB). Ehhez hasonl forma jelenik meg az Object Pascal nyelvben is (ON DO).
118
VIII. Kivtelkezels try catch throw finally mely kritikus programrsz kvetkezik ha problma van, mit kell csinlni kifejezs, kivtelkezels tadsa, kivtel(ek) deklarlsa kritikus blokk vgn biztos vgrehajtdik
A try blokkot kvetheti legalbb egy catch blokk, de tbb is kvetkezhet. Ha a try blokk utn nincs elkap (catch) blokk, vagy a meglv catch blokk tpusa nem egyezik a keletkezett kivtellel, akkor a keretrendszer kivtelkezel felgyelete veszi t a vezrlst. A C++ nyelv kivtelkezel lehetsge megengedi azt, hogy a catch blokk tetszleges hibatpust kapjon el, mg a C# ezt kicsit korltozza. A C# nyelvben a catch blokk tpusa csak a keretrendszer ltal biztostott Exception osztlytpus, vagy ennek egy utdtpusa lehet. Termszetesen mi is kszthetnk sajt kivtel tpust, mint az Exception osztly utdosztlyt. Ezek utn nzznk egy egyszer pldt a kivtelkezels gyakorlati hasznlatra. Plda:
int i=4; int j=0; try { i=i/j; }
// 0-val osztunk
VIII. Kivtelkezels
catch (Exception ) { Console.WriteLine("Hiba!"); } finally { Console.WriteLine("Vgl ez a Finally blokk is lefut!"); }
A fenti pldban azt lthatjuk, hogy a rendszerknyvtr hasznlatval, pldul a nullval val oszts prblkozsakor, a keretrendszer hibakivtelt generl, amit elkapunk a catch blokkal, majd a finally blokkot is vgrehajtjuk. A plda egsz szmokhoz kapcsoldik, gy meg kell jegyezni, hogy gyakran hasznljk az egsz aritmetikhoz kapcsoldan a checked s az unchecked mdostkat is. Ezek a jelzk egy blokkra vagy egy fggvnyre vonatkozhatnak. Ha az egsz aritmetikai mvelet nem brzolhat, vagy hibs jelentst tartalmaz, akkor a checked blokkban ez a mvelet nem kerl vgrehajtsra. Plda:
int i=System.Int32.MaxValue; checked { i++; // OverflowException kivtel keletkezik } int j=System.Int32.MaxValue; unchecked { j++; // OverflowException kivtel nem keletkezik } Console.WriteLine(i); // -2147483648 lesz a kirt rtk // ez azonos a Syste.Int32.MinValue // rtkvel
Termszetesen nemcsak a keretrendszer lthatja azt, hogy a normlis utastsvgrehajtst nem tudja folytatni, ezrt kivtelt generl, s ezzel adja t a vezrlst, hanem maga a programoz is. Termszetesen az, hogy a programoz mikor ltja szksgesnek a kivtel generlst, az r van bzva. Plda:
int i=4; try
VIII. Kivtelkezels
if (i>3) throw new Exception(); // ha i>3, kivtel indul } catch (Exception ) // mivel az i rtke 4, itt folytatdik a vgrehajts { Console.WriteLine("Hibt dobtl!"); } finally { Console.WriteLine("Vgl ez is lefut!"); } {
A kivtelkezelsek egymsba gyazhatk. Tbbfle abnormlis jelensg miatt lehet szksg kivtelkezelsre, ekkor az egyik kivtelkezel a msiknak adhatja t a kezels lehetsgt, mondvn ez mr nem az n asztalom, menjen a kvetkez szobba, htha ott a cmzett (throw). Ekkor nincs semmilyen paramtere a throw-nak. Ez az eredeti hibajelensg jragenerlst, tovbbadst jelenti. Plda:
int i=4; try { if (i>3) throw new Exception(); // ha i>3, kivtel indul } catch (Exception ) { Console.WriteLine("Hibt dobtl!"); throw; //a hiba tovbbtsa // ennek hatsra , ha a program nem kezel tovbbi kivtel // elkapst, a .NET keretrendszer lesz a kivtel elkapja. // gy szabvny hibazenetet kapunk, majd a // programunk lell }
VIII. Kivtelkezels akkor az Indexhibra jellemz plusz informcik nem lesznek elrhetk! Mivel egy stpus egyben dinamikus utdtpusknt is megjelenhet, ezrt a hibakezel blokkokat az rkls fordtott sorrendjben kell definilni. Plda:
using System; public class Hiba:Exception { public Hiba(): base() { } public Hiba(string s): base(s) { } } public class IndexHiba:Hiba { public IndexHiba(): base() { } public IndexHiba(string s): base(s) { } } int i=4; int j=0; try { if (i>3) throw new Hiba("Nagy a szm!"); } catch (IndexHiba h ) { Console.WriteLine(h); } catch (Hiba h ) // csak ez a blokk hajtdik vgre { Console.WriteLine(h); } catch (Exception ) { Console.WriteLine("Hiba trtnt, nem tudom milyen!"); } finally // s termszetesen a finally is { Console.WriteLine("Finally blokk!"); }
VIII. Kivtelkezels Ahogy korbban lttuk, minden objektum a keretrendszer Object utdjnak tekinthet, ennek a tpusnak pedig a ToString fggvny a rsze, gy egy tetszleges objektum kirsa nem jelent mst, mint ezen ToString fggvny meghvst. A fenti plda gy meghvja az Exception osztly ToString fggvnyt, ami szvegparamter mellett kirja mg az osztly nevt s a hiba helyt is. Befejezsl nzzk meg a korbban ltott verem plda megvalstst kivtelkezelssel kiegsztve. Plda:
using System; class verem { Object[] x; int mut; public verem(int db) { x=new object[db]; mut=0;
// elemek trolsi helye // veremmutat // konstruktor // helyet foglalunk a vektornak // az els szabad helyre mutat
} // NEM DEFINILUNK DESTRUKTORT, // MERT AZ AUTOMATIKUS SZEMTGYJTSI // ALGORITMUS FELSZABADTJA A MEMRIT public void push(Object i) { if (mut<x.Length) { x[mut++]=i; // beillesztettk az elemet } else throw new VeremTele("Ez bizony tele van!"); } public Object pop() { if (mut>0) return x[--mut]; // ha van elem, akkor visszaadjuk a tetejrl else throw new VeremUres("res a verem bartom!"); } } public class VeremTele:Exception { public VeremTele(): base("Tele a verem!") { }
VIII. Kivtelkezels
public VeremTele(string s): base(s) { }
} public class VeremUres:Exception { public VeremUres(): base("res a verem!") { } public VeremUres(string s): base(s) { } } class program { public static void Main() { verem v=new verem(6); try { Console.WriteLine(v.pop()); // mivel a verem res, kivtelt fog dobni } catch (VeremUres ve) // amit itt elkapunk { Console.WriteLine(ve); } v.push(5); v.push("alma"); Console.WriteLine(v.pop()); } }
11. bra
VIII. Kivtelkezels
VIII.3. Feladatok
1. Mikor is hogyan hasznljuk a kivtelkezelseket? 2. Mit jelent a checked, unchecked kulcssz, hogyan tudjuk hasznlni? 3. Hogyan tudunk sajt kivtelt (tpust) definilni? 4. Olvassa be a msodfok egyenlet paramtereit. Szmolja ki a gykket, ha a diszkriminns negatv szm, hasznlja a rendszerknyvtr kivtelkezelsi lehetsgt! 5. Ksztsen Diszkriminns_negatv kivtelt. Oldja meg az elz feladatot ennek segtsgvel!
IX. Input-Output
A be- s kiviteli szolgltatsok nem rszei a nyelvnek. A programok a szabvnyos knyvtrban lv fggvnyek segtsgvel tartjk a krnyezetkkel a kapcsolatot. Ez a fajta kapcsolattarts nem csak a C# nyelvben rt programok sajtossga. A C++-bl szrmaztathat nyelvek hasonlan hasznljk az inputoutput mveleteket, mert gy azok egyszerbben s rugalmasabban kezelhetk.
Mindkt utasts jradefinilt formj, teht lteznek a Write(int), Write(double) stb. knyvtri utastsok. A kir utastsoknak ltezik egy msik vltozata is:
Write( string, adat, ); WriteLine( string, adat, );
Ez a vltozat a C vilgbl ismert megoldst valstja meg (printf). Az els paramter, mint eredmnyszveg, kapcsos zrjelek { } kztt a msodik stb. paramterek behelyettestst vgzi. A kapcsos zrjelek kztt a szvegek formzsi lehetsgeit hasznlhatjuk. Ezen formzsrt felels karaktersorozat hrom rszbl llhat, ahol a formzs alakja a kvetkez: {sorszm[, szlessg ][:kijelzsi_forma]}
126
IX. Input-Output Az els rsz 0-tl kezdden egy sorszm, azt mondja meg, hogy a szveg utni kirand adatok kzl hnyadikat kell behelyettesteni. Ha van msodik rsz, akkor az vesszvel elvlasztva kvetkezik, s a teljes adatszlessget hatrozza meg. Ha a szlessg pozitv, akkor az jobbra, ha negatv, akkor balra igaztst jelent az adott szlessgen bell. A hinyz karaktereket n. white space (helykz) karakterekkel tlti fel. Ha van harmadik rsz, akkor az a kettspont utn kvetkezik, s meghatrozza az adat tpust, kijelzsi formjt. Az adattpus jelzsre az albbi karakterek hasznltak: c e x pnznembeli (currency) kijelzs tudomnyos, tzes alap hatvnykijelzs hexadecimlis formtum
Ezek mellett a 0 s a # helyirtk karakterek hasznlhatak. A 0 biztosan megjelentend helyirtket, mg a # opcionlisan ha van oda rtk, megjelentend karaktert jelent. Plda:
int i=5; Console.WriteLine("Az {0}. mvelet eredmnye: {1}",i,4*i); Console.WriteLine(" A szm: {0:c}",25); // pnznem : 25,00 Ft. Console.WriteLine("A kapott sszeg: {0,10:c}",25); // 10 karakter szles pnznem formj kijelzs jobbra igaztva Console.WriteLine(" A szm: {0: 0.###e+0}",25); // 2.5E+1 Console.WriteLine("A kapott szm: {0,10:00.#0}",25.1); // 10 szles jobbra igaztott 25.10 lesz a kijelzs Console.WriteLine("A kapott szm: {0,10:x}",25); // 10 szles jobbra igaztott hexa alak (19) kijelzs
A System.String osztly Format fggvnye az imnti forma alapjn tud egy eredmnyszveget kszteni (formzni). Beolvass: int Read(); // egy karaktert olvas be Ha nem sikerl az olvass, akkor 1 az eredmny. Ha egyb hiba jelentkezik, akkor IOException kivtelt dob a Read utasts. Plda:
char c=(char)Console.Read(); string ReadLine();// egy egsz sort olvas
Ha nem sikerl az olvass, akkor OutOfMemoryException vagy IOException kivtelt dob a ReadLine utasts. A knyvtr nem tartalmaz tpusos beolvassi lehetsget, viszont rendelkezsre llnak a Convert osztly konvertlsi mezfggvnyei. Plda:
string s=Console.ReadLine(); int j=Convert.ToInt32(s); // egsz konvertls int i=Convert.ToInt32(s,16); //konvertls 16-os szmrendszerbl Console.WriteLine(i);
Ha nem sikerl a konvertls, akkor a konvertlsi hibnak megfelel kivtelt dob a Convert osztlyfggvnye. Ezt a kivtelkezelst hasznlva szmok beolvassra, az albbi pldt, mint egy lehetsges megvalstst tekinthetjk. Nzzk meg a Struktrk fejezet vgn hasznlt pldnkat azzal a kiegsztssel, hogy a kor mez olvasst a konverzi kivtelfigyelsvel egsztjk ki. Plda:
using System; struct struktra_plda { public int kor; public string nv; } class strukra_hasznl { public static void Main() { // struktra_plda vektor struktra_plda [] spv=new struktra_plda[5]; int i=0; // beolvass while(i<5) { spv[i]=new struktra_plda(); Console.WriteLine("Krem az {0}. elem nevt!",i); string n=Console.ReadLine(); spv[i].nv=n; Console.WriteLine("Krem az {0}. elem kort!",i);
IX. Input-Output
while(true) { try { n=Console.ReadLine(); spv[i].kor=Convert.ToInt32(n); } catch(Exception e) { Console.WriteLine("Te kis csibsz, a kor az szm!"); Console.WriteLine("Azt add meg mg egyszer! "); continue; } break; } i++; } // kirs for(i=0;i<5;i++) { Console.WriteLine(spv[i].nv); Console.WriteLine(spv[i].kor); } } }
IX. Input-Output
IX. Input-Output Knyvtrakkal kapcsolatosan a Directory osztly statikus fggvnyei llnak rendelkezsre. Ha megnyitottunk egy binris llomnyt, akkor rsra a legfontosabb BinaryWriter fggvnyek a kvetkezk: Write(adat) Flush() Close() Seek(mennyit, honnan) // tbb pldnyban ltezik, brmely // alaptpust kir. // pufferek rtse // fjlzrs // fjlmutat pozicionlsa
A legfontosabb BinaryReader fggvnyek: Read() ReadInt32() Close() // tbb pldnyban ltezik, brmely //alaptpust beolvas. // egsz szm beolvassa // ms alaptpusokra is ltezik // fjlzrs
A fjl olvassi mveletek fjl vge esetn EndOfFileException kivtelt dobnak, gy ha nem tudjuk, mennyi adat van egy llomnyban, akkor ennek megfelelen try blokkban kell az olvasst vgezni! Ezek utn nzznk egy rvid pldt:
using System; using System.IO; class fileteszt { private static string nev = "Test.data"; public static void Main(String[] args) { // j llomny ltrehozsa if (File.Exists(nev)) { Console.WriteLine("{0} mr ltezik!", nev); return; } // FileStream ltrehozsa FileStream fs = new FileStream(nev, FileMode.CreateNew); // a filestream hozzrendelse binris rshoz. BinaryWriter w = new BinaryWriter(fs); // adatkirs.
IX. Input-Output
for (int i = 0; i < 5; i++) { w.Write( i); } w.Close(); fs.Close(); // fjlzrs // Create the reader for data. fs = new FileStream(nev, FileMode.Open, FileAccess.Read); BinaryReader r = new BinaryReader(fs); // olvass. for (int i = 0; i < 5; i++) { Console.WriteLine(r.ReadInt32()); } w.Close(); } }
A legfontosabb StreamReader fggvnyek: int Read() ReadLine() Close() Peek() // karaktert beolvas. // egsz sort beolvas // ms alaptpusokra is ltezik // fjlzrs // a kvetkez karaktert kapjuk a fjlbl // de nem mdosul a fjlpozci
A .NET keretrendszer knyvtra a binris s a szveges fjlok mellett sok egyb tpus fjl i/o mveleteit is tmogatja, ilyenek pldul az XmlTextReader s az XmlTextWriter, amelyek XML llomnyok kezelst segtik el, vagy a HtmlTextWriter, s a HtmlTextReader, amelyek HTML llomnyok rst, olvasst vgzik. A fjl input-output szolgltatsokra is, mint ltalban minden knyvtri szolgltatsra igaz az, hogy a megfelel megoldsi elkpzels kialaktshoz rdemes az online, MSDN segtsg szolgltatst is ignybe venni.
IX.3. Feladatok
1. Mit jelent a standard input-output lehetsge? 2. Milyen formzsi lehetsgeket ismer? 3. Mi a klnbsg a binris s szveges fjl kztt? 4. rja ki a szmot decimlis, hexadecimlis formban balra, majd jobbra igaztva 20 szlessgben! 5. Trolunk egy nevet s egy szmot, rjuk ki ezeket adatok .bin nvvel binris, majd adatok.txt nvvel szveges formban!
X. Prhuzamos programvgrehajts
A feladatok gyorsabb, hatkonyabb elvgzsnek rdekben az utbbi vekben specilis lehetsgknt jelent meg a prhuzamos programvgrehajts. Gondolhatunk a tbbfeladatos opercis rendszerekre, vagyis arra pldul, hogy mikzben a programunkat fejlesztjk, s valamilyen szvegszerkesztt hasznlunk, a produktvabb munkavgzs rdekben, gondolkodsunkat serkentend, kedvenc zennket hallgathatjuk szmtgpnk segtsgvel. A prhuzamos programvgrehajts programjaink szintjn azt jelenti, hogy az opercis rendszer fel tbb vgrehajtsi feladatot tudunk definilni. Pldul egy adatgyjtsi feladatban az egyik szl az adatok gyjtst vgzi, a msik szl pedig a korbban begyjttt adatokat dolgozza fel. A .NET keretrendszer, ahogy tbb ms fejleszteszkz is, lehetsget ad arra, hogy egy program tbb vgrehajtsi szlat definiljon. Ezekrl a vgrehajtsi szlakrl az irodalomban, online dokumentciban threads, threading nven olvashatunk.
134
X. Prhuzamos programvgrehajts Ezek utn az els pldaprogram a kvetkezkppen nzhet ki: Plda:
using System; using System.Threading; class program { public static void szal() { Console.WriteLine("Ez a szlprogram!"); } public static void Main() { Console.WriteLine("A fprogram itt indul!"); ThreadStart szalmutato=new ThreadStart(program.szal); // ltrehoztuk a fonal fggvnymutatt, ami a // szal() fggvnyre mutat Thread fonal=new Thread(szalmutato); // ltrehoztuk a prhuzamos vgrehajtst vgz objektumot // paramterl kapta azt a delegltat (fggvnyt)amit // majd vgre kell hajtani fonal.Start(); // elindtottuk a fonalat, valjban a szal() fggvnyt // a fonal vgrehajtsa akkor fejezdik be amikor // a szal fggvnyhvs befejezdik Console.WriteLine("Program vge!"); } }
X. Prhuzamos programvgrehajts Interrupt(): az aktulis szl megszaktsa. A szl objektum interrupt hvsa ThreadInterruptedException esemnyt okoz a szl vgrehajtsban. Abort(): az aktulis szl befejezse, valjban a szlban egy AbortThreadException kivtel dobst okozza, s ezzel befejezdik a szl vgrehajtsa. Ha egy szlat abortltunk, nem tudjuk a Start fggvnnyel jraindtani, a start utasts ThreadStateException kivtelt dob. Ezt a kivtelt akr mi is elkaphatjuk, s ekkor, ha gy ltjuk, hogy a szlat mgsem kell abortlni, akkor a Thread.ResetAbort() fggvnyhvssal hatlyon kvl helyezhetjk az Abort() hvst. IsAlive: tulajdonsg, megmondja, hogy a szl l-e Suspend(): a szl vgrehajtsnak felfggesztse Resume(): a felfggeszts befejezse, a szl tovbbindul
Ezek utn nzzk meg a fenti programunk mdostst, illusztrlva ezen fggvnyek hasznlatt. Plda:
using System; using System.Threading; class program { public static void szal() { Console.WriteLine("Ez a szlprogram!"); Thread.Sleep(1000); // egy msodpercet vrunk Console.WriteLine("Letelt az 1 msodperc a szlban!"); Thread.Sleep(5000); Console.WriteLine("Letelt az 5 msodperc a szlban!"); Console.WriteLine("Szl vg!"); } public static void Main() { Console.WriteLine("A fprogram itt indul!"); ThreadStart szalmutato=new ThreadStart(program.szal); // ltrehoztuk a fonal fggvnymutatt, ami a // szal() fggvnyre mutat Thread fonal=new Thread(szalmutato); // ltrehoztuk a prhuzamos vgrehajtst vgz objektumot // paramterl kapta azt a delegltat (fggvnyt), amit // majd vgre kell hajtani fonal.Start(); // elindtottuk a fonalat, valjban a szal() fggvnyt
X. Prhuzamos programvgrehajts
Thread.Sleep(2000); // vrunk 2 msodpercet Console.WriteLine("Letelt a 2 msodperc a fprogramban, a szlat felfggesztjk!"); fonal.Suspend(); // fonal megll Thread.Sleep(2000); Console.WriteLine("Letelt az jabb 2 msodperc a fprogramban, a szl vgrehajtst folytatjuk!"); fonal.Resume(); // fonal jraindul fonal.Join(); // megvrjuk a fonalbefejezdst Console.WriteLine("Program vge!");
} }
12. bra
Ha tbb szlat is definilunk, vagy akr csak egyet, mint a fenti pldban, szksgnk lehet a vgrehajtsi szl prioritsnak lltsra. Ezt a szlobjektum Priority tulajdonsg lltsval tudjuk megtenni az albbi utastsok valamelyikvel:.
fonal.Priority=ThreadPriority.Highest fonal.Priority=ThreadPriority.AboveNormal fonal.Priority=ThreadPriority.Normal fonal.Priority=ThreadPriority.BelowNormal fonal.Priority=ThreadPriority.Lowest // // // // // legmagasabb alap fltt alaprtelmezett alap alatt legalacsonyabb
X. Prhuzamos programvgrehajts
X. Prhuzamos programvgrehajts
// szl1 definils public static void szal2() { Console.WriteLine("Ez a szl2 programinduls!"); // egy msodpercet vrunk Console.WriteLine("Adatments meghvsa szal2-bl!"); a.mentes("-"); Console.WriteLine("Szl2 vge!"); } public static void Main() { Console.WriteLine("A fprogram itt indul!"); ThreadStart szalmutato1=new ThreadStart(program.szal1); ThreadStart szalmutato2=new ThreadStart(program.szal2); // ltrehoztuk a fonal fggvnymutatt, ami a // Thread fonal1=new Thread(szalmutato1); Thread fonal2=new Thread(szalmutato2); fonal1.Start(); fonal2.Start(); // // Console.WriteLine("Program vge!"); } }
13. bra
X. Prhuzamos programvgrehajts Ebbl a futsi eredmnybl az ltszik, hogy a fonal1 s a fonal2 mentse, azaz ugyanannak a fggvnynek a vgrehajtsa prhuzamosan trtnik! (Csak azrt kerlt egy kis vrakozs a ciklusba, hogy szemlletesebb legyen a prhuzamos fggvnyfuts, a + s karakterek vltott kirsa.) A + s a karakterek vltakoz kirsa, azaz a kt fonal trzsnek vltakoz vgrehajtsa nem jr klnsebb gonddal. De gondoljunk pldul egy olyan esetre, amikor az adatment fggvny soros portra rja a mentsi adatokat archivlsi cllal, vagy vezrel valamilyen eszkzt. Ekkor lnyeges az adatok sorrendje, s ez a fajta futsi eredmny nem kielgt. Teht alapvet igny a tbbszl vgrehajts esetn, hogy biztostani tudjuk egy fggvny, egy utasts megszaktsmentes (ezt gyakran thread safe lehetsgnek nevezik), n. szinkronizlt vgrehajtst. Ha egy adat mdostst, egy fggvny hvst egy idpontban csak egy vgrehajtsi szlnak szeretnnk engedlyezni, akkor erre tbb lehetsgnk is knlkozik. Csak a leggyakrabban hasznlt lehetsgeket emltjk, hiszen nem tudjuk, s nem is clunk az sszes lehetsg referenciaszer felsorolsa. Automatikus szinkronizcinak nevezi a szakirodalom azt a lehetsget, mikor egy egsz osztlyra belltjuk ezt a szolgltatst. Ehhez kt dolgot kell megtennnk: 1. A Synchronization() attribtummal kell jellni az osztlyt. Az attribtumokkal a kvetkez fejezet foglalkozik, gy most egyszeren fogadjuk el ezt az osztlyra, fggvnyre, vltozra llthat informcit. 2. Az osztlyt a ContextBoundObject osztlybl kell szrmaztatni. Plda:
[Syncronization()] class szinkronosztly: ContextBoundObject { int i=5; // egy idbencsak egy szl fr hozz public void Novel() // ezt a fggvnyt is csak egy szl // tudja egyszerre vgrehajtani { i++; } }
Az automatikusan szinkronizlt osztlyoknl a statikus mezket tbben is elrhetik. Ezt orvosolja a fggvnyek, blokkok szinkronizcija, amit gyakran manulis szinkronizcinak is neveznek.
X. Prhuzamos programvgrehajts Egy fggvny szinkronizlt vgrehajtst a legegyszerbben a MethodImplAttribute attribtum belltsval rhetjk el. Ezt mind pldny, mind pedig statikus fggvnyre alkalmazhatjuk.
[MethodImplAttribute(MethodImplOptions.Syncronized)] public void safe_fv() { }
Egy fggvny szinkronizlt vgrehajtsra knl egy msik megoldst a Monitor osztly enter s exit fggvnye. Amg egy monitor a belpssel vd egy vgrehajtsi blokkot, addig egy msik szl azt nem tudja meghvni. Ekkor a kvetkezkppen mdosul az adatments fggvnye:
public void mentes(string s) { Monitor.Enter(this); Console.WriteLine("Adatments elindul!"); for(int i=0;i<50;i++) { Thread.Sleep(1); Console.Write(s); } Console.WriteLine(""); Console.WriteLine("Adatments befejezdtt!"); Monitor.Exit(this); }
Az eredmnyben azt lthatjuk, hogy az a blokk, amit a Monitor vd, megszakts nlkl fut le.
14. bra
X. Prhuzamos programvgrehajts Hasonl eredmnyt kaphatunk, ha a C# nyelv lock utastsval vdjk a kvnt blokkot. Ha a fenti fggvnyt a lock nyelvi utastssal vdjk, azt a fordt a kvetkez alakra alaktja:
Monitor.Enter(this); try { utastsok; } finally { Monitor.Exit(this); }
A teljessg ignye nlkl a Monitor osztly kt fggvnyrl mg szt kell ejtennk. Az egyik a Wait, ami a nevbl sejtheten lelltja a szl vgrehajtst, s a paramterobjektum zrst befejezi. Monitor.Wait(objektum); A fggvny hasznlathoz a Pulse fggvny is hozztartozik, ami az objektumra vrakoz szlat tovbbengedi. Monitor.Pulse(objektum); Hasonl szolgltatst ad a Windows API mutex (mutual exclusive, klcsns kizrs) lehetsgnek megfelel Mutex osztly. Lnyeges klnbsg a monitorhoz kpest, hogy a kizrlagos vgrehajtshoz megadhatjuk azt is, hogy ez mennyi ideig lljon fenn. (WaitOne fggvny)
class adatok { Mutex m=new Mutex(); public void mentes(string s) { m.WaitOne(); Console.WriteLine("Adatments elindul!"); for(int i=0;i<50;i++) { Thread.Sleep(1); Console.Write(s); } Console.WriteLine(""); Console.WriteLine("Adatments befejezdtt!"); m.Release(); } }
X. Prhuzamos programvgrehajts Mg manulisabb adat vagy utasts szinkronizcit biztost a ReadWriterLock, valamint az Interlocked osztly is. Ezek s a tovbbi szinkronizcis lehetsgek ismertetse tlmutat e knyv keretein. Ha knyvtri szolgltatsokat vesznk ignybe, pldul MSDN Help, az egyes hvsok, osztlyok mellett olvashatjuk, hogy thread safe-e vagy nem a hasznlata, attl fggen, hogy a szinkronizlt hozzfrs biztostott-e vagy sem. A szlakkal kapcsolatban befejezsl meg kell emlteni a [STAThread] illetve az [MTAThread] attribtumot, ami azt mondja meg, hogy Single (egy) vagy Multi (tbb) szlat tartalmaz alkalmazsknt definiljuk a programunkat COM komponensknt val egyttmkdsnl. Alaprtelmezs a [STAThread] hasznlata, ami pldul a Windows alkalmazsok Drag and Drop jellemzk hasznlata esetn kvetelmny is.
X.4. Feladatok
1. Mit rtnk prhuzamos programvgrehajts alatt? 2. Hogyan tudunk szlat definilni? 3. Mit jelent a lock utasts? Milyen knyvtri szolgltats felel meg ennek az utastsnak? 4. Ksztsen programot, amely kt sket ember beszlgetst szimullja! Mindketten egy-egy fjlban troljk a mondkjukat! 5. Hasznljunk szinkronizlst, mdostsuk az elz feladatot gy, hogy a mondatvgeknl lehet a msik szereplnek tvenni a beszd fonalt!
XI. Attribtumok
Kpzeljk el, hogy definiltunk egy j tpust (osztlyt), minden adatnak, fggvnymeznek elksztettk a megfelel kezelst, jelentst, hasznlatt, azaz a tpusunk hasznlatra ksz. Mgis, egyes mezk vagy esetleg az egsz tpus mell bizonyos plusz informcikat szeretnnk hozzrendelni. Pldaknt nzznk kt ilyen, a mindennapi programozsi feladataink sorn is elfordul esetet! Els plda: Egy program ltalban tbb tpussal, adattal dolgozik. Ezek kztt az adatok kztt lehet nhny, amelyek rtkre a program kvetkez indulsakor is szksgnk lehet. Ezeket a program vgn elmentjk a registry-be. (A registry a korbbi Windows ini llomnyokat vltja fel, programhoz ktd informcikat tudunk ebben az opercis rendszerbeli adatbzisban trolni.) Termszetesen innen be is olvashatjuk ezeket az adatokat. A programunk elvgzi ezt a mentst is, a visszaolvasst is. Ha viszont felteszi valaki a krdst a programban, hogy jelenleg kik azok, akiket a registry-ben is trolunk, akkor erre nincs ltalnos vlasz! Minden programba bele kell kdolni azt, hogy melyek a mentett adataink! Hasznos lenne, ha nem kellene ezt megtenni, csak jellhetnnk ezeket a mezket, s ezt a jellst ksbb kikereshetnnk. Msodik plda: Ez a plda taln kicsit tvolabb ll az informatiktl, de nem kevsb letszer. Definiljuk vagy nem is kell definilnunk, mert egybknt is lteznek az emberek klnbz csoportjait! Ebbe a definciba rtsk bele a normlis hasznlathoz szksges sszes tulajdonsgot (nem, foglalkozs, letkor, vgzettsg, )! Emellett szksgnk lehet mondjuk egy olyan informcira, hogy pldul az illet fradidrukker-e! Termszetesen az alaptulajdonsgok kz is felvehetnnk ezt a jellemzt, de mivel ennek az adatnak a tpus tnyleges mkdshez semmi kze nincs nem fradidrukker is vgezheti rendesen a dolgt , ezrt ez nem lenne szerencss. Az ilyen plusz informcik elhelyezsre nyjt lehetsget a C# nyelvben az attribtum. Az attribtumok olyan nyelvi elemek, melyekkel fordtsi idben osztlyokhoz, fggvnyekhez vagy adatmezkhz informcikat rendelhetnk. Ezek az informcik aztn futsi idben lekrdezhetk.
144
XI. Attribtumok
Egy attribtum, ahogyan egy kivtel is, mr a nevvel informcit hordoz. Termszetesen lehetsgnk van ehhez az osztlyhoz is adatmezket definilni, ha gy tljk meg, hogy a tpusnv, mint attribtum mg kevs informcival br. Ekkor mint egy rendes osztlyhoz adatmezket tudunk definilni. Az adattpusokra annyi megkts van, hogy felhasznli osztlytpus nem lehet. Ellenben lehetnek a rendszerbeli alaptpusok (bool, int, float, char, string, double, long short, object, Type, publikus enum). Adatok inicializlsra konstruktort definilhatunk. Egy attribtum osztlyban ktfle adatot, paramtert klnbztethetnk meg. Pozicionlis s nevestett paramtert. Pozicionlis paramter a teljesen normlis konstruktorparamter. Nevestett paramternek nevezzk a publikus elrs adat- vagy tulajdonsgmezket. A tulajdonsgmeznek rendelkezni kell mind a get, mind a set taggal. A nevestett paramtereknek gy adhatunk rtket, mintha norml pozicionlis konstruktorparamter lenne, csak a konstruktorban nincs semmilyen jellsre szksg. A konstrukci kicsit hasonlt a C++ nyelvben hasznlatos alaprtelmezett (default) paramterek hasznlathoz. Ezek utn nzzk meg a fradi_szurkol attribtumunkat kt adattal kiegsztve. Az egyik legyen az az informci, hogy hny ve ll fenn ez a viszony, mg a msik az, hogy az illet trzsszurkol-e? Plda:
class fradi_szurkol:Attribute { private int v; // hny ve szurkol private bool trzsgrda; // trzsszurkol-e public fradi_szurkol(int e) { v=e; // konstruktor belltja a normal paramtert }
XI. Attribtumok
public bool Trzsgrda { get { return trzsgrda; } set { trzsgrda=value; } }
Ekkor a Trzsgrda tulajdonsgmezt nevestett paramternek hvjuk. Az elnevezst az mutatja, hogy erre a tulajdonsgra a konstruktorhvs kifejezsben tudunk hivatkozni, mintha ez is konstruktorparamter lenne, pedig nem is az! Plda:
[fradi_szurkol(5,Trzsgrda=true)]
utastst kell a program elejre berni. A tpusinformci visszanyershez jellemzen a Type osztly GetType() statikus fggvnyt kell meghvni, ami egy paramtert vr tlnk, azt az osztlytpust, amit ppen fel szeretnnk dolgozni.
Type t=Type.GetType("program");
XI. Attribtumok Ekkor a programosztlyomat szeretnm a t nev tpusler objektumon keresztl elemezni. A kapott t objektumra megkrdezhetem pldul, hogy osztly-e:
if (t.IsClass()) Console.WriteLine("Igen");
Tovbbi lehetsgekhez a Type osztly online dokumentcijnl nincs jobb forrs. A tpushoz tartoz attribtumok listjt a GetCustomAttributes() fggvnyhvs adja meg. Ez eredmnyl egy Attribute vektort ad. Jellemz mdon, ezen egy foreach ciklussal lpdelnk vgig:
foreach (Attribute at in t.GetCustomAttributes()) { // feldolgozzuk az at attribtumot }
Ez a feldolgozs osztlyokra (pl. program, stb.) vonatkoz attribtumokra megfelel. Elfordulhat viszont olyan is, mikor fggvnyekhez vagy adatmezkhz rendelnk attribtumot. Ekkor elszr az adott tpus fggvnyeit vagy az adatmezit kell megkapnunk, majd ezen informcik attribtumait kell lekrdeznnk. Egy tpus fggvnyeit a GetMethods() hvs szolgltatja, eredmnyl egy MethodInfo tpust ad.
foreach(MethodInfo m in t.GetMethods()) { foreach (Attribute at in m.GetCustomAttributes()) { // feldolgozzuk az m fggvny at attribtumt } }
Ha egy attribtumosztlyt definilunk, rjuk az osztly neve utn az Attribute szt, ahogyan azt gyakran tancsknt is megfogalmazzk a szakirodalomban,
XI. Attribtumok hiszen gy knnyen meg lehet klnbztetni a rendes osztlyoktl. Termszetesen ebben az esetben is elhagyhatjuk az attribute szcskt a hasznlat sorn, mert azt a fordt odarti. Teht ekkor a fradi_szurkol attribtumosztlyt a kvetkezkppen definiljuk:
class fradi_szurkolAttribute:Attribute { }
Ezek utn megnzzk a fradi_szurkol attribtumunk definilst s hasznlatt egy kerek pldn keresztl. A plda nem hasznlja az imnti Attribute kiegsztses defincit. Plda:
using System; using System.Reflection; class fradi_szurkol:Attribute { private int ev; // hny ve szurkol private bool torzsszurkolo; // vajon trzsszurkol-e public fradi_szurkol(int e) // az e rendes, pozicionlis { // paramter ev=e; } public override string ToString() { string s="Ez az ember fradiszurkol! vek szma:"+ev+"Trzsszurkol:"+torzsszurkolo; return s; } // az albbi Torzsszurkol tulajdonsg nevestett // fradi_szurkol paramter, mert publikus s van get s set
XI. Attribtumok
// rsze, amivel az adott torzsszurkolo logikai mezt llthatjuk public bool Trzsszurkol { get { return torzsszurkolo; } set { torzsszurkolo=value; } } } class ember { string nev; public ember(string n) { nev=n; } } class adatok{} //nem fontos, hogy rdemi informcit tartalmazzon class program { // attribtum belltsa [fradi_szurkol(35)] public ember en= new ember("Zoli"); // a norml konstruktort hvtuk meg, azok a mezk, amiket nem // inicializl, alaprtelms szerint kerlnek belltsra // 0, ha szm, false ha bool, illetve null, ha referencia // Egy attribtum csak a kvetkez adat vagy fggvny vagy // osztlyra hat!!! // gy a kvetkez adatok tpus vltoznak nincs kze // a fradi_szurkol attribtumhoz // public adatok a=new adatok(); // [fradi_szurkol(42,Trzsszurkol=true)] public ember te= new ember("Pali"); // Pali mr trzsszurkol public static void Main() {
XI. Attribtumok
program p=new program(); Console.WriteLine("A fprogram itt indul!"); Type t=Type.GetType("program"); foreach( FieldInfo mezo in t.GetFields()) { Console.WriteLine(mezo.FieldType); // meztpus kirsa Console.WriteLine(mezo.Name); // meznv krsa if ((mezo.GetCustomAttributes(true)).Length>0) { foreach (Attribute at in mezo.GetCustomAttributes(true)) { // megnzzk fradiszurkol-e fradi_szurkol f=at as fradi_szurkol; if (f!=null) // igen ez a mez fradiszurkol Console.WriteLine(at.ToString()); } } else Console.WriteLine("Ez az adat nem rendelkezik attribtummal!"); } Console.WriteLine("Program vge!"); } }
15. bra
XI. Attribtumok
Ekkor az osztlyattribtumok csak osztlyok jellsre hasznlhatk. Elfordulhat, hogy egy attribtumot tbbszr is hozz szeretnnk rendelni egy adathoz, akkor ennek az osztlynak az AllowMultiple nevestett paramtert igazra kell lltani.
[AttributeUsage(AttributeTargets.Class, AllowMultiple=true)]
System.ConditionalAttribute: Egy szveg a paramtere. Csak fggvnyhez kapcsolhatjuk, s az a fggvny, amihez kapcsoltuk csak akkor hajtdik vgre, ha a paramterl adott szveg definilt. Plda:
[Conditional("alma")] void almafuggveny() { Console.WriteLine("Alma volt!"); } #define alma almafuggveny(); #undefine alma almafuggveny(); // hvs rendben // hvs elmarad
XI. Attribtumok A feltteles vgrehajts fggvnyek ktelezen void visszatrsek, s nem lehetnek virtulisak, vagy override jelzvel elltottak! Ezeket a kirtkelseket az elfordt nzi vgig. System.ObsoleteAttribute: egy zenet(szveg) a paramtere, ha egy fggvny elavult, s javasolt a mellzse, akkor hasznlhatjuk.
XI.4. Feladatok
1. Mi az attribtum, hogy tudjuk hasznlni? 2. Hogyan definilhatunk sajt attribtumot? 3. Mi a klnbsg a rendes s nevestett attribtum paramter kztt? 4. Ksztsnk Hisz_e_a_mesben attribtumot! Definiljuk az ember osztlyt, majd alkalmazzuk az attribtumot egyes 'pldnyaira'! Mdostsuk az elz attribtumot gy, hogy meg tudjuk adni azt az idt amilyen rgta hisz valaki a mesben!
153
XII. Szabvnyos adatments ltre. Ha ez a ktfle lehetsg nem elg, akkor egyni formz osztlyok definilhatk. A formz osztlyok a System.Runtime.Serialization.Formatters.Binary s a System.Runtime.Serialization.Formatters.Soap nvterekben tallhatk. A szerializci folyamata az albbi lpsekbl ll: 1. Ki kell jellni egy FileStream objektumot, ami a program kapcsolatt jelenti az llomnnyal. 2. Definilni kell egy formz objektumot, ez jelenleg binris vagy szveges lehet. A szveges formz objektum ltrehozshoz a System.Runtime.Serialization.Formatters.soap.dll referencit a projekthez kell csatolni (Project nzet \ References \ jobb egrgomb \ Add reference).
16. bra
3. A formz objektum Serialize fggvnyvel mentjk az adatokat. 4. Bezrjuk a fjlkapcsolatot. Ezek utn nzzk a lehetsget bemutat pldaprogramot! Plda:
using using using using using System; System.IO; System.Runtime.Serialization; System.Runtime.Serialization.Formatters.Binary; System.Runtime.Serialization.Formatters.Soap;
A program magyarzatul csak annyit, hogy miutn lefuttatjuk, a projekt debug knyvtrban (ebbe a knyvtrba kerl a lefordtott program) ltrejn a ser.bin, illetve a ser.txt llomny. Ha ezt megnzzk, lthatjuk, hogy mg az elbbi binris, az utbbi XML formtum. Visszaolvass hasonl mdon, csak a formatter objektum Deserialize fggvnyhvssal vgezhet el.
XII. Szabvnyos adatments Ebben az esetben a mentsi folyamat visszavezeti az adatok mentst a rendszertpusok mentsre. Ahhoz, hogy ezt megtegye neknk, egyetlen dolgot kell tennnk, a sajt tpusunkat a menthet, Serializable attribtummal kell jellnnk. Mdostsuk a pldaprogramunkat gy, hogy definilunk egy ember tpust, amit mg hasznlnia kell a programunknak. A mdostott forrsszveg a kvetkezkppen nz ki: Plda:
using using using using using System; System.IO; System.Runtime.Serialization; System.Runtime.Serialization.Formatters.Binary; System.Runtime.Serialization.Formatters.Soap;
[Serializable] // az attribtum hatsra a formz lekezeli a tpus szerializcijt class ember { string nev; int kor; public ember(string n, int k) { nev=n; kor=k; } } class serprog { // program adatai int i=2; double d=3.5; string s="fradi"; // a sajt tpus hasznlata ember e=new ember("Zoli", 34); public static void Main() { serprog p=new serprog(); //fjlstream ltrehozsa FileStream fb=File.Create("ser.bin"); // Binaryformatter kszts FileStream fs=File.Create("ser.txt"); BinaryFormatter b=new BinaryFormatter(); SoapFormatter so=new SoapFormatter(); //Binris ments b.Serialize(fb,p.i); b.Serialize(fb,p.d);
} }
A gyakorlati munka sorn elfordulhat pldul az osztly bels szerkezete nem engedi meg , hogy nem bzhatjuk r a formzra a tpusunk vgigelemzst s az elemek mentst. Ebben az esetben a valdi szerializcis szolgltatst vgz fggvnyeket neknk kell az osztlyunkba implementlni. Azon tl, hogy a [Serializable] attribtumot definilni kell, az osztlyunknak mg implementlnia kell az ISerializable interface-t is. Ebben a deszerializci szmra egy specilis konstruktort s egy GetObjectData fggvnyt kell definilni. Az interface s a fggvnyek hosszabb elemzse nlkl nzzk meg az ennek megfelelen mdostott ember osztlyunkat. A program kdja vltozatlan, ezrt azt nem listzzuk ide. Plda:
[Serializable] // az attribtum hatsra a formz lekezeli a tpus szerializcijt class ember:ISerializable // az interface kt plusz fggvnydefincit r el { string nev; int kor; public ember(string n, int k) { nev=n; kor=k; } internal ember(SerializationInfo si, StreamingContext st) { // elemek visszalltsa nev=si.GetString("nev"); kor=si.GetInt32("kor"); }
XII.3. Feladatok
1. Mit neveznk szabvnyos mentsnek? 2. Milyen hasonl megvalstsokat ismer ms fejleszt rendszerben? 3. Milyen szabvnyos mentseket tmogat a fejleszt rendszer? 4. A msodfok egyenlet (VIII.3. fejezet 4. feladat) adatait mentsk el binris formban! 5. Definiljunk egy szurkol osztlyt (nv, kedvenc_csapat), s biztostsuk ennek a tpusnak szabvnyos menthetsgt!
HashTable: olyan vektorilis adatsorozat, ahol egy kulcsindexhez tartozik egy rtk. A kulcs hash rtkhez rendeli az adatot. Gyakran asszociatv vektornak hvjk ezt a szerkezetet.
159
XIII. Knyvtrak, tvoli s webknyvtrak Queue: a sor adatszerkezet megvalstsa. Az az elem megy elsnek ki a sorbl, amely elsnek berkezett. (First in, first out.) SortedList: rendezett lista. Hasonl szerkezet, mint a HashTable, melyek elemei a kulcs alapjn sorba vannak rendezve. Kulcs s index alapjn is az elemekhez lehet frni. Stack: verem adatszerkezet. Az utoljra betett elemet tudjuk mindig kivenni. (Last in, first out) Pldaknt tekintsk a kvetkez ArrayList s Queue hasznlatt bemutat mintaprogramot: Plda:
using System; using System.Collections; public class mintacol { public static void Main() { // j ArrayList objektum ltrehozsa. ArrayList elemek = new ArrayList(); elemek.Add( "Hajr" ); // alaprtelmezsben a mret nvelhet (IsFixedSize==false) elemek.Add( "Fradi" ); elemek.Add(25); for (int i=0;i<elemek.Count;i++) Console.WriteLine(elemek[i]); // j sor (Queue) objektum ltrehozsa. Queue sor = new Queue(); // adat sorba rsa sor.Enqueue( "mzes" ); sor.Enqueue( "maci" ); sor.Enqueue( 3.1415 ); // mind az Arraylist, mind a sor implementlja az IEnumerable // interface-t, gy a foreach hasznlhat foreach(object o in sor) Console.WriteLine(o); // ArrayList objektumhoz hozzadjuk a sort. elemek.AddRange( sor ); // elem kivtele a sorbl Console.WriteLine(sor.Dequeue()); Console.WriteLine(sor.Dequeue()); Console.WriteLine(sor.Dequeue());
// az IEnumerable alapjn vgiglpdelnk az elemeken public static void PrintValues( IEnumerable adatok) { IEnumerator adat = adatok.GetEnumerator(); while ( adat.MoveNext() ) Console.WriteLine( adat.Current ); } }
A fenti forrskdot teszleges szvegszerkesztbe berva, az albbi parancssor segtsgvel lefordthat. (A keretrendszer mindegyik fordtja indthat parancssorbl.)
vbc /target: library /out:DllDemo Demo.vb
Termszetesen j projektet ksztve, az osztlyknyvtr tpust vlasztva a Visual Studio.NET krnyezetbe is berhatjuk ezt a pr sort, majd a Build menpont segtsgvel lefordthatjuk. Az elkszlt DllDemo.dll llomny egy tipikus knyvtri llomny lesz, amit brmely msik alkalmazs hasznlhat, pontosan gy, ahogy a rendszerknyvtrakat. Ksztsnk most egy C# nyelv alkalmazst, amely szeretn hasznlni a DllDemo knyvtri szolgltatst. A hasznlathoz az alkalmazshoz kell csatolni (add reference) ezt a knyvtrllomnyt, majd a using DllDemo utastssal a DllDemo nvtr elrhetsgt is biztostani kell.
XIII. Knyvtrak, tvoli s webknyvtrak tmeneti, proxy objektum ltrehozsa, mely az adatcsert elvgzi a tvoli objektum (pontosabban annak proxy objektuma) s a helyi alkalmazs kztt. Tvoli objektum aktivlsa, lettartama Kommunikcis csatornt Tcp vagy Http alapon alakthatunk ki. Hasznlat eltt regisztrlni kell egy csatornt, ami egy kommunikcis porthoz kttt. Egy alkalmazs nem hasznlhat ms alkalmazs ltal lefoglalt csatornt. A ktfle kommunikci hasznlata kztt a legfontosabb klnbsg az adatok tovbbtsban van. A Http protokoll a SOAP szabvnyt hasznlja az adatok tovbbtsra XML formban. A Tcp csatorna binris formban tovbbtja az adatokat. A proxy objektum reprezentlja a tvoli objektumot, tovbbtja a hvsokat, visszaadja a hvsi eredmnyt. A tvoli objektumok a szerver oldalon automatikusan, vagy kliens oldali aktivlssal jhetnek ltre. Az automatikus objektumok esetben megklnbztetnk egy krst kiszolgl objektumot (Single call) vagy tbb krst kiszolgl (Singleton) objektumot. Meg kell termszetesen jegyezni, hogy a szolgltatst, a programot magt el kell indtani, hiszen a klienshvs hatsra csak az alkalmazs egy kiszolgl tpusa jn automatikusan ltre! Ezt vagy gy rjk el, hogy az alkalmazsunkat futtatjuk egy konzolsori parancs kiadsval, vagy mint regisztrlt szervzt az opercis rendszer futtatja! Mieltt egy konkrt pldt nznnk, beszlni kell a paramter tads lehetsgrl. Egy alkalmazson bell a keretrendszer biztostja az adatok paramterknti tadst, tvtelt. Esetnkben nem egy alkalmazsrl van sz, hanem egy kliensrl s egy (vagy tbb) szerverrl, melyek klnbz krnyezetben (app. domainben) futnak. Emiatt az adatok tadsa sem lehet ugyanaz, mint egy alkalmazson bell. A klnbz alkalmazsi krnyezetben fut programok kztti adatcsere folyamatt Marshaling kifejezssel illet az irodalom, utalva arra, hogy ez a fajta alkalmazsi hatron tvezet adatforgalom mst jelent, mint egy alkalmazsi krnyezet esetben. Egy adatot hrom kategriba sorolhatunk a .NET keretrendszerben, a tvoli adattads (Marshaling) szempontjbl: 1. rtk szerint tadott adatok. Ezen tpusok a szabvnyos szerializcit (ments) tmogat objektumok. (Marshal-by-value). Ekkor a tpus a [Serializable] attribtummal jellt. A krnyezet alaptpusai (int, stb.) menthetek, gy rtk szerint tadhat adatok. 2. Referencia szerint tadott adatok. Ezek a tpusok ktelezen a MarshalByRefObject tpusbl szrmaznak.
XIII. Knyvtrak, tvoli s webknyvtrak 3. Alkalmazsdomainek kztt nem tadhat tpusok. Ebbe a kategriba esik minden olyan tpus, amelyik nem MarshalByRefObject utd, vagy rendelkezik a [Serializable] attribtummal. A legfontosabb tulajdonsgok ismertetse utn nzznk egy egyszer pldt. Manulisan fogjuk a szerverkiszolglkat is futtatni az egyszersg kedvrt. A pldnkban kt szerverszolgltatst ksztnk, az egyik http, mg a msik tcp hlzati kommunikcit folytat. A forrskdot mind parancssorbl, mind a krnyezetbl tudjuk fordtani. Ez utbbi esetben a Project referencia ablakban a projekthez kell adni a System.Runtime.Remoting nvteret. Az albbi plda egy bajnokszerver tpust definil, regisztrlja magt, s ms feladata nincs. Enterre a Main program azrt vrakozik, mert ha engedjk befejezdni, mivel nem rendszerrsz-szolgltats, nem lehet elrni. Plda:
using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; public class BajnokSzerver : MarshalByRefObject { public string foci; public static int Main(string [] args) { TcpChannel chan1 = new TcpChannel(8085); // 8085 tcp port lefoglalva ChannelServices.RegisterChannel(chan1); // regisztrci rendben RemotingConfiguration.RegisterWellKnownServiceType( typeof(BajnokSzerver), "bajnok", // kliens oldalon elrhet // szolgltats neve WellKnownObjectMode.Singleton); System.Console.WriteLine("Program vge, nyomjon entert"); System.Console.ReadLine(); return 0; } public BajnokSzerver() { foci="Magyar bajnoksg"; Console.WriteLine("Remote szerver aktivlva!"); }
Indtsuk el egy-egy ablakban elszr a szerver-, majd a kliensprogramot, ahogy a kvetkez kpen is ltszik.
17. bra
Termszetesen a szerverablakban lthat eredmny a szemlletessget szolglja, a vals alkalmazsok (mivel nem is futnak nll ablakban) nem rogatnak semmit a kpernyre. A korbbi feladathoz hasonl kliens-szerver alkalmazsksztsi lehetsget is biztost a keretrendszer, gynevezett WebRequest, WebResponse modellt hasznlva, vagy a klasszikus TCP, UDP protokollok hasznlatval (TcpListener, TcpClient, UdpClient). Az osztlyok a System.Net nvtrben tallhatk. A System.Net sszes szolgltatsa a System.Net.Sockets nvtr szolgltatsaira pl. A System.Net.Sockets nvtr a WinSock32 API megvalstsa. Ezen hlzati alkalmazsok ksztsnek lehetsge tlmutat e knyv keretein, gy nem is rszletezzk azokat.
namespace WebService1 { /// <summary> /// Summary description for Service1. /// </summary> public class Service1 : System.Web.Services.WebService { public Service1() { InitializeComponent(); } //Component Designer generated code [WebMethod] public string Ki_a_bajnok(int ev) {
} } }
A forrskd service1.asmx.cs nven tallhat. Fordts utn az IIS kiszolgl webservice1 virtulis knyvtrba kerl service1.asmx llomnyra hivatkozva tudjuk futtatni a feladatot. A fenti kiszolgl hasznlathoz webreferencit kell a ksztend projekthez adni, ahol meg kell adni a Web Service cmt a kvetkez mdon: http://localhost/webservice1/service1.asmx Ezt legegyszerbben az Add Web Reference menpontban tehetjk meg:
18. bra
A futsi eredmny megadja a vrt csapatnevet. Termszetesen a using nvtr hasznlattal az s objektumdefincit egyszerbben rhatjuk.
using webhasznal.localhost; // projekt neve utn jn a webreferencia neve Service1 s=new Service1(); // A hasznlatban mr nincs vltozs
A webkiszolgl szolgltatst, nemcsak egy kliens programbl, hanem a legltalnosabban hasznlt webes kliens programunkbl, pldul az Internet Explorerbl is kiprblhatjuk (19. bra). A szolgltatsokat ltalnosan ler nyelv (Web Service Description Language, WSDL) termszetesen XML formban adja meg, ezt az albbi krssel tudjuk megnzni: http://localhost/webservice1/service1.asmx?WSDL
19. bra
A webszolgltatsnak ezt a hasznlatt gyakran szinkronhvsnak nevezzk. Ugyanis ebben az esetben a Ki_a_bajnok hvsa az eredmny visszarkezsig nem tr vissza. Ez webes kiszolgls esetn gyakran hosszabb idt is ignybe vehet. St az sem kizrt, hogy adott idn bell vissza sem tr. Ha figyelmesen megnzzk a projekt knyvtrunkat, akkor ebben megjelent egy Web References knyvtr is. Ebben aztn annyi knyvtrt tallunk, ahny webreferencit csatoltunk a projektnkhz. Esetnkben tallunk egy localhost knyvtrat (localhost a neve a http://localhost/webservice1 URL ltal megadott webknyvtrnak), ebben egy References.cs llomnyt. Ha ezt megnzzk, ltjuk, hogy nem csak a megrt fggvnynk van lerva benne, hanem egy BeginKi_a_bajnok s egy EndKi_a_bajnok hvs is. Ezek a fggvnyek adnak lehetsget arra, hogy egy ilyen webkiszolgln elhelyezett szolgltatst ne csak a sajt nevvel, gynevezett szinkronhvssal tudjunk elrni, hanem aszinkron mdon is. A Begin-nel kezdd fggvny mindig azonnal visszatr, eredmnyl egy IAsyncResult objektumot kapunk. Ezen az objektumon keresztl krdezhetjk meg, hogy befejezdtt-e a vgrehajts. Esetnkben a msodik paramter s a harmadik is a null, jelezve azt, hogy az aszinkron hvs eredmnyt az IAsyncResult objektumon keresztl akarjuk lekrdezni. Egybknt a msodik paramter egy deleglt (callback) fggvny, ami ltal adott fggvny kerl vgrehajtsra akkor, amikor megrkezik az eredmny. A harmadik paramter
XIII. Knyvtrak, tvoli s webknyvtrak egy krs llapotot jelz objektum, amiben a callback fggvny meg tudja nzni az eredmnyparamtereket. Az albbi plda nem hasznlja ezeket a paramtereket, hanem az IAsyncResult IsCompleted tulajdonsgt figyelve vrakozik az eredmnyre. Plda:
static void Main(string[] args) { // // TODO: Add code to start application here // localhost.Service1 s=new localhost.Service1(); Console.WriteLine("Szinkronhvs eredmnye: {0}",s.Ki_a_bajnok(2004)); IAsyncResult e=s.BeginKi_a_bajnok(2004,null,null); // elindtottuk a fggvnyhvst, majd addig //vrakozunk, amig az eredmny meg nem rkezik while(e.IsCompleted!=true) Console.WriteLine("Vrjuk az eredmnyt!"); // megjtt az eredmny // kiolvassuk azt string eredmeny=s.EndKi_a_bajnok(e); Console.WriteLine("Az aszinkronhvs eredmnye: {0}",eredmeny); }
Esemnyvezrelt krnyezetben, grafikus alkalmazs ksztsekor ez a mdszer kzenfekv lehet. A program futsnak eredmnye jl illusztrlja az aszinkron vgrehajts jellegzetessgt, amit az albbi futsi kp is jl szemlltet:
20. bra
XIII.4. Feladatok
1. Milyen rendszer knyvtri tpusokat ismer? 2. Mi a klnbsg a rendszer knyvtri s a web knyvtr szolgltats kztt? 3. Mit neveznk szinkron, illetve aszinkron knyvtri hvsnak? 4. rjon programot, amely egy listban trolja a kifizetett telefonszmlk sszegt! Valstsa meg a beolvasst, kirst fggvnyknt! 5. Ksztsen WebService-t, amely egy adott nvrl eldnti, hogy olimpiai bajnok neve-e!
XIV. Az elfeldolgoz
XIV.1. Szimblumdefinci hasznlata
Az elfeldolgoznak vagy elfordtnak szl utastsok mindig a # karakterrel kezddnek. Az elfordtnak szl makr definilsi lehetsgnek a formja:
#define nv Plda:
#define menu_h // menu_h szimblum definilva
A defincik hatsa az adott modul vgig tart. Egy azonost definilsnak gyakori formja a kvetkez: Plda: #define ALMA Ekkor nem definilunk helyettestsi rtket, gy ez csak annyit mond meg az elfordtnak, hogy ettl kezdve az ALMA sz legyen ismert. Ez gyakran hasznlt md a feltteles fordts azonostinak definilsra. Ha mr nincs szksgnk egy korbban definilt azonostra, s meg szeretnnk krni az elfordtt, hogy felejtse azt el, akkor a kvetkez elfordtnak ezt az utastst adhatjuk:
174
XIV. Az elfeldolgoz
21. bra
A fenti kpen az ember osztly tartalmt ltjuk, mg a tbbi egysgt (adatok, program) nem, azokat csak jelli a szvegszerkeszt, hogy lteznek, de pillanatnyilag nem rdekesek. Ez a segtsg nagyobb llomnyok szerkesztsnl hasznos, hiszen a szerkesztablakban jobban a lnyegre tudunk figyelni. Ezt a szolgltatst egszti ki a
#region alma osztlyok, fggvnyek helye #endregion alma
rgi, terletdefinci. Ekkor az alma blokkban, rgiban definilt osztlyok, fggvnyek egyszerre hzhatk ssze vagy nyithatk ki.
XIV. Az elfeldolgoz
Mindhrom alakot kvetheti a #else direktva, majd ktelezen zrja: #endif #line sorszm A fordt gy viselkedik, mintha a kvetkez sor a sorszmmal megadott sor lenne. #line default eredeti sorszm visszalltsa
XIV.4. Hibazenet
Ha mr az elfordt felfedez valamilyen hibt, akkor hibazenetet ad, s befejezi az elfordtst. A vezrldirektva formja: #error hibaszveg Plda:
#ifndef c# #error Sajnos nem a megfelel fordtt hasznlja! #endif
XIV.5. Feladatok
1. Mik az elfordt jellemz szolgltatsai? 2. Hogy definilhatunk s szntethetnk meg egy azonostt? 3. Mit jelent a rgi definci? 4. Az eddig elksztett programjait mdostsa rgi defincikkal! Figyelje meg, hogy mennyivel ttekinthetbb vlt a programjnak a kdja! 5. Definilja gy a msodfok egyenletet megold fggvnyt, hogy csak akkor fordtsuk le, ha szksges!
177
XV. Nem felgyelt kd hasznlata A program futtatsa utn az albbi rendszer-zenetablak jelenik meg:
22. bra
23. bra
XV. Nem felgyelt kd hasznlata Ezt a belltst parancssori krnyezetben a csc fordtnak az /unsafe kapcsolja hasznlatval rhetjk el. Ezek utn nzznk egy klasszikus C++ nyelvszer maximumrtk meghatrozst. Az albbi pldban a max fggvny egy egsz vektor legnagyobb rtkt hatrozza meg. Plda:
using System; class unmanaged { unsafe int max(int* v, int db) { int i=0; int m=v[i++]; while(i<db) { if (m<v[i]) m=v[i]; i++; } return m; } int[] s=new int[10]{1,2,3,4,5,0,21,11,1,15}; unsafe public static void Main() { int h=0; unmanaged u=new unmanaged(); fixed (int* m= &u.s[0]) { h=u.max(m,10); } Console.WriteLine(h); } }
XV.3. Feladatok
1. Mit jelent a nem felgyelt kd (unsafe)? 2. Hogyan tudunk Win32 API fggvnyt meghvni? 3. Mi a fixed vltoz? 4. Hogyan hasznlhatunk mutatkat egy C# programban? 5. Ksztsen unsafe fggvnyt, amelyik a paramter vektort nagysg szerint sorbarendezi!
Ez a kdsor azt jelenti, hogy a form utdosztlyunk (Form1) ltal kpviselt grafikus fellet illeszkedjen az opercis rendszer felgyeletbe, s az ablak jelenjen meg. Ez az ablak elszr termszetesen res, a f feladat ppen az, hogy megfelel tartalommal lssuk el, ezltal elksztve a kvnt programot. A program elksztsben a legnagyobb segtsget a grafikus knyvtri elemek, a Windows Forms nvtr objektumai (form ablak, cmke, nyomgomb stb.) adjk. Ezt a lehetsghalmazt a Toolbox ablak mutatja, amit a rajzszg segtsgvel gyakran a kpernyre helyeznk. Ksztsnk a legjellemzbb tulajdonsgok bemutatsra egy msodfok egyenletet megold programot. Az j projekt nevnek adjuk meg a masodfok nevet, vlasszuk ki a Windows Application sablont, majd a kapott felletre rajzszgezzk ki a Toolbox ablakot.
180
24. bra
A forrsllomnyt megnzve azt lthatjuk, hogy ebben az llapotban a programunk valjban egy form (ablak) objektumbl ll (new Form1()). Ezt a Tulajdonsgok (Properties) ablak lenyl mezjbl is megllapthatjuk, hiszen nem tudunk msik objektumot kivlasztani. A Tulajdonsgok (Properties) ablakban tervezskor llthatjuk be a kivlasztott komponensnk legjellemzbb tulajdonsgait, kezd adatait. Ezek a tulajdonsgok futs kzben is hasonl mdon megvltoztathatk. Az egyszer adatok mellett ez az ablak ad lehetsget egyes objektumok esemnykezel paramternek belltsra. Ez azrt lnyeges, mert ebben a krnyezetben a programok valdi tevkenysgt ezek a fggvnyek vgzik. gy valjban programkszts cmn kicsit egyszerstve nincs msrl sz, mint hogy olyan grafikus elemekkel ptsk fel a programablakot, amelyek esemnykezeli ppen a kvnt feladatot oldjk meg. Ezek utn nzzk a clul kitztt egyszer feladatot, a msodfok egyenlet megoldst, amin keresztl a legjellemzbb lpseket szemlltetni tudjuk. Mieltt nekifognnk a megoldsnak, le kell szgeznnk, hogy a karakteres felleten hasznlt beolvassi s krsi lehetsgek nem hasznlhatak. Erre a
XVI. Grafikus alkalmazsok alapjai clra a Toolbox ablak elemeit tudjuk hasznlni. A leggyakrabban hasznlt elem kirsra a cmke (Label), mg beolvassra a szvegdoboz (TextBox). Ezen elemek segtsgvel alaktsuk ezutn ki a program felhasznli fellett, ahol a cmkkkel informcit runk ki, mg a szveges beolvas elemek a paramterek beolvasst biztostjk. A formra tegynk cmkket, s a cmke Text tulajdonsg mezjbe a megjelenteni kvnt szveget rjuk bele. A szvegmezk alaprtelmezett Text mez rtkt pedig trljk ki. Ezek alapjn egy kevs munkval az albbi fellet alakthat ki:
25. bra
Azt termszetesen nem lltom, hogy ez a legszebb kialakts, de a clnak megfelel. A fenti grafikus tervezs utn lthatjuk a Tulajdonsg ablak objektum kivlasztmezjben, hogy minden egyes nll vezrl (label, textbox) egy-egy vltoz nvvel jelenik meg. Ezeket a neveket (label1, label2, stb.) a keretrendszer automatikusan adja, s ha szksgnk van ezek ksbbi hasznlatra, akkor a programtervezsi szempontok figyelembevtelvel adjunk beszdes nevet ezen vltozknak. Ezt a Tulajdonsg ablak Name mezjnek mdostsval tehetjk meg. A hrom egytthat beolvasst biztost textmeznek rendre az a, b, c neveket adtam, mg a megoldst megjelent cmknek a megoldas nevet. Az ablakot reprezentl C# nyelvi forrskd az albbiak szerint mdosul.
Ezeket a bejegyzseket a keretrendszer automatikusan elvgzi. Azonban meg kell jegyezni, hogy a vezrlink elnevezst csak ebben a kdrszben vgzi el a keretrendszer, gy ha utlag neveznk t vezrlket, akkor a programkdbeli vltozsokrl magunknak kell gondoskodnunk. A program tnyleges megoldst az egyetlen nyomgomb esemnykezel fggvnye fogja elvgezni. A vezrlelem esemnyeit az albbi Tulajdonsg ablakban lthatjuk.
26. bra
XVI. Grafikus alkalmazsok alapjai Kettt kattintva a nyomgombra, a keretrendszer belltja a nyomgomb Click esemnykezeljt, a forrskdba berja ennek a fggvnynek a kerett, s szmunkra nem marad ms htra, mint a valdi programkdot a fggvny trzsbe berni. A feladat ismertsge megengedi, hogy klnsebb magyarzat nlkl lssuk az esemnykezel fggvny trzst:
private void button1_Click(object sender, System.EventArgs e) { double a1=Convert.ToDouble(a.Text); double b1=Convert.ToDouble(b.Text); double c1=Convert.ToDouble(c.Text); double m1,m2; double d=b1*b1-4*a1*c1; // diszkriminns if (d<0) megoldas.Text="Nincs megolds, a diszkriminns negatv."; else { m1=(-b1+Math.Sqrt(d))/2*a1; m2=(-b1-Math.Sqrt(d))/2*a1; megoldas.Text=String.Format("A megolds x1={0} s x2={1}",m1,m2); } }
A programot futtatva, miutn berjuk a megfelel egytthatkat, az albbi formban kapjuk meg az eredmnyt. (Termszetesen tovbbi finomts rfrne erre a programra, de ennek elvgzst a kedves Olvasra bzom.)
27. bra
28. bra
XVI. Grafikus alkalmazsok alapjai Miutn megadtuk a nevet, elkszl a kvetkez res weboldal. A ltrehozott Webform1.aspx az res HTML oldal (ezrt is van HTML nzete) s a htterben meghzd programfjl (Webform1.aspx.cs). Lthat, hogy a Toolbox ablakban a korbbi Windows Forms felirat helyett Web Forms olvashat, mutatva, hogy ezek a vezrlk web alap alkalmazsokhoz hasznlhatak. A Tulajdonsg ablak egyetlen objektuma a DOCUMENT objektum lesz, ami termszetesen magnak a HTML dokumentumnak felel meg. Ezek tulajdonsgrtkeit mdosthatjuk, pldul a Title mez rtkt, megadva ezzel a weboldal cmkjt, vagy a bgColor paramterrel belltva a kvnt httrsznt. A kapott kperny a kvetkez alak lesz:
29. bra
A Windows Form megoldshoz hasonlan ksztsk el a msodfok egyenlet megoldst ebben a krnyezetben is. Ehhez els lpsknt alaktsuk ki a programunk fellett az elz pldhoz hasonlan, majd a nyomgomb esemnykezel fggvnyt definiljuk.
namespace webmasodfok { /// <summary> /// Summary description for WebForm1. /// </summary> public class WebForm1 : System.Web.UI.Page { protected System.Web.UI.WebControls.Label Label1; protected System.Web.UI.WebControls.Label Label2; protected System.Web.UI.WebControls.Label Label3; protected System.Web.UI.WebControls.Label Label4; protected System.Web.UI.WebControls.TextBox a; protected System.Web.UI.WebControls.TextBox b; protected System.Web.UI.WebControls.TextBox c; protected System.Web.UI.WebControls.Label megoldas; protected System.Web.UI.WebControls.Button Button1; private void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN: This call is required by the ASP.NET Web Form Designer. // InitializeComponent(); base.OnInit(e); }
private void InitializeComponent() { this.Button1.Click += new System.EventHandler(this.Button1_Click); this.Load += new System.EventHandler(this.Page_Load); } #endregion private void Button1_Click(object sender, System.EventArgs e) { double a1=Convert.ToDouble(a.Text); double b1=Convert.ToDouble(b.Text); double c1=Convert.ToDouble(c.Text); double m1,m2; double d=b1*b1-4*a1*c1; // diszkriminns if (d<0) megoldas.Text="Nincs megolds, a diszkriminns negatv."; else { m1=(-b1+Math.Sqrt(d))/2*a1; m2=(-b1-Math.Sqrt(d))/2*a1; megoldas.Text=String.Format("A megolds x1={0} s x2={1}",m1,m2); } } } }
A program fordtsa s futtatsa utn a 30. brn lthat Internet Explorer bngszben fut alkalmazst kapjuk, vagyis a clunkat elrtk. Ebben a fejezetben kitekintsknt csak a legfontosabb krnyezeti belltsokrl, fogalmakrl tudtunk szlni. A grafikus alkalmazsok lehetsgeit, a segtsgnkre lv grafikus vezrlelemek tulajdonsgait, webes, mobil s/vagy adatbzis kapcsolattal rendelkez alkalmazsok ksztst egy kvetkez ktet keretben szeretnnk megmutatni.
30. bra
XVI.3. Feladatok
1. Mi a feladata a grafikus alkalmazs Main fggvnynek? 2. Mi a klnbsg a Windows s az ASP.NET alkalmazs kztt? 3. Milyen feltteleknek kell teljeslni ahhoz, hogy ASP.NET alkalmazst tudjunk kszteni? 4. Ksztsen alkalmazst, amely egy tglatest 3 oldalt beolvasva meghatrozza a trfogatt s felsznt! (Hasznljon cmkket s szvegmezket!) 5. Ksztse el az elz feladatot webes alkalmazsknt is.
Irodalomjegyzk
1. 2. 3. 4. 5. 6. 7. 8. 9. Brian W. Kernigham, Dennis M. Ritchie : A C programozsi nyelv Mszaki Knyvkiad, Budapest 1985, 1988 Bjarne Stroustrup: C++ programming language AT&T Bell Lab, 1986 Tom Archer : Inside C# MS Press, 2001 Microsoft C# language specifications MS Press, 2001 John Sharp, Jon Jagger: Microsoft Visual C#.NET MS Press, 2002 Ills Zoltn: A C++ programozsi nyelv ELTE IK, Mikrolgia jegyzet, 1995- David S.Platt: Bemutatkozik a Microsoft.NET Szak Kiad, 2001 Ills Zoltn: A C# programozsi nyelv s krnyezete Informatika a felsoktatsban 2002, Debrecen David Chappell: Understanding .NET Addison-Wesley, 2002
190
Fodor Gbor Antal: Eszttikus dokumentumok Worddel, ISBN 963 210 971 6 A knyv ttekinti a kiadvnyok ksztsnek vszzadok alatt kialakult sajtossgait, majd tpusonknt trgyalja azokat. Rszletesen megismerkedhetnk a hivatalos dokumentumok, a tanulmnyok, a marketing jelleg kiadvnyok ksztsnek szablyaival, de a szerz kitr a knyv s az jsg jelleg kiadvnyok ksztsre is. Eszkzknt mindvgig a Word szvegszerkesztt hasznlja. Szentirmai Rbert: Bevezets a Microsoft Office Project 2003 hasznlatba, ISBN: 963 86514 4 X A knyv rszletesen trgyalja a projectmenedzsment s nyomon kvets elmleti alapjait s megvalstst a Microsoft Project 2003 segtsgvel. Holczer Jzsef: Webszerkeszts egyszeren, ISBN: 963 86514 9 0 Knyvnk az nll webszerkesztsbe vezeti be az Olvast. Trgyalja a FrontPage 2003 hasznlatt, a HTML nyelv alapjait s a dinamikus elemek kezelst. Kezdknek, kzphaladknak s rettsgizknek egyarnt ajnljuk. Farkas Csaba Szab Marcell: A programozs alapjai Visual Basicben, ISBN 963 214 293 4 Knyvnkben szeretnnk egyfell az Olvast bevezetni programozs vilgba, msfell egy olyan hatkony programozsi nyelvet bemutatni, mellyel knnyedn tud j programokat kszteni (VB 6), automatizlhatja a Windows folyamatait (VB Script) s j funkcikkal bvtheti az Office programcsomagot (VB makrk). Figyelembe vettk az emelt szint rettsgi vonatkoz kvetelmnyeit is. Farkas Csaba: Programozsi ismeretek halad felhasznlknak, ISBN: 963 86514 2 3 Knyvnkbl az emelt szint rettsgire kszlk megismerkedhetnek az elvrt webszerkesztsi, SQL s programozsi ismeretekkel, illetve a VB.NET-tel. Bdy Bence: Az SQL pldkon keresztl, ISBN: 963 210 860 4 Az SQL megismersnek leghatkonyabb eszkze kidolgozott mintapldk tanulmnyozsa. A knyv ezrt 30 feladatcsoportba rendezve tbb mint 80
fokozatosan nehezed, valsgh feladat kidolgozsval vezeti be az Olvast az SQL alkalmazsba. Egy-egy feladat megoldsra tbb megoldst is kzl, s az nll gyakorls rdekben a fejezetek s a knyv vgn kzel 100, tovbbi feladatot is tallhatunk. Holczer-Benkovics: Windows Server 2003 hlzatok kezelse, ISBN: 963 214 693 X A knyv a Windows Server 2003 alap hlzatok zemeltetsbe (hardver ismeretek, TCP/IP protokoll, Windows Server 2003, ISA Server 2000, Exchange Server 2003 zemeltetse, teleptsi ismeretek) tanknyvszeren vezeti be a kezd rendszergazdkat.