C# nyelvi áttekintő A „Programozás C# nyelven (Illés Zoltán)” könyv 2008-as kiadásának nyomdokain… Az alábbi diákon felvetődő számok, a könyvbeli oldalszám(oka)t jelölik.
Változók / állandók (32-34) Változók/állandók definiálása char ch; int egy, tizenegy; const float g=9.81; // valós konstans g=2.3; // !! HIBA const int min = 0; // egész konstans Változók inicializálása char s = ’a’; int []a = {1,2,3}; char[]b = „Egy”;
Elemi típusok (34-39) char (2 byte -> unikód ábrázolás) string char c = ’a’; string fontosabb operátorok: +, +=, @ [] a string indexelése: pl. "szia"[1] = z // read-only. @”C:\programok\alma.txt” -> érzékeny karakterek fontosabb függvények… később Érdekesség: string s = „vmi” + a; // a integer (a –ra a ToString meghívódik ilyenkor) Érdekesség, hogy C-ben pont a char a legkisebb foglalási egységet használó típus (1 byte), míg C#-ban ez a típus 2 byteos, ami egyel nagyobb a boolean foglalásánál.
Elemi típusok (34-39) int (4 byte) long (8), short (2), sbyte, float (4), double (8), decimal (16) u előjel: unsigned, nem előjeles uint, ulong, ushort, byte void (fv. visszatérő paramétere) bool (1 byte) true/false http://msdn.microsoft.com/en-us/library/s1ax56ch(v=vs.110)
Egy operandusú operátorok (45-46) new int[]a; a = new int(); // egy egész számára elegendő hely foglalás a = new int[5]; // 5 egész szám !, ++, -- a = ++b -> // hatása: b=b+1; a=b; // b=3 akkor b=4 és a = 4 a = b++ -> // hatása: a=b; b=b+1; // b = 3 akkor b=4 és a =3
Egy operandusú operátorok (45-46) (típus) kifejezés // típuskényszerítés (cast) int a = (int)9.81F; Console.WriteLine(a); // 9 Másik lehetőség a konvertálásra int a = int.Parse("1"); // a = 1 int b = Convert.ToInt32("1"); // b = 1
Convert.ToCTSTípusnév A Convert használható minden gyakori típus átkonvertálásához. Létezik Convert.ToInt32() … Convert.ToFloat() CTS = Common Type System CTS Boolean, Int16, Int32, Int64, Float, Double, String, Decimal, Byte, Char
Két operandusú operátorok (46-52) *, /, % (maradékképzés) +, - i is int // i az int típusból van-e létrehozva var a = 16; if (a is int) { Console.WriteLine("Szám!"); } if (a is String) { Console.WriteLine("Szöveg!"); i as int // két operandusú típuskényszerítés (csak referenciákra és nullablekre)
Egyéb operátorok (52 - 56) Három operandusú e1 ? e2 : e3 Két operandusú értékadó operátorok: +=, -=, *= Továbbiak: http://msdn.microsoft.com/en-us/library/6a71f45d
Adattípusok, Tömbök (57-61) int[]numbers; // vektordefiníció numbers = new int[10]; numbers = new int[20];// automatikus szemétgyűjtés Kézzel inicializált tömb: int[] n = {3,4,5,6}; int[] n = new int[]{3,4,5,6}; int[]n = new int[4]{3,4,5,6}; Logikai vektor automatikus elemei: false, Referencia vektor-é : null Továbbá: Multidimenziós vektor, Vektorok vektora,…
Adattípusok, Struktúrák (62-66) struct név{ <hozzáférés,alap privát> típus mezőnevek; <hozzáférés,alap privát> függvénydefiníció; } Hozzáférési szintek: private, public, internal (assemblyn belül érhető el)
Adattípusok, Struktúrák (62-66) Fontos megjegyezni: Nem lehet struktúrából származtatni Nem lehet a mezőket deklaráláskor inicializálni Van beépített, default konstruktor (paraméter nélkül) de az sem inicializálja a mezőket. (saját kell) Bár érték típusú a struktúra, ha saját konstruktorral szeretnénk inicializálni, azért a new operátorral kell létrehozni. Bár ekkor is a vermen (stack) fog tárolódni.
Struktúra példa struct Pont { public int x; public int y; } Pont p; // OK p.x = 5; p.y = 6;
Struktúra példa (2) struct Pont { private int x; private int y; public Pont(int a, int b) { x = a; y = b; } Pont p(2,3); // HIBÁS, bár C++-ban jó lenne. Pont p = new Pont(2, 3); // OK, de így a stacken jön létre
Utasítások, kifejezések (67) Kifejezés utasítás kifejezés; Létezik a kifejezés nélküli ; utasítás, és értelme is van, például végtelen ciklus írása: for(;;){ // végtelen ciklus }
Elágazás utasítás (68-69) Alapvetően: if(kifejezés){ utasítás; } if(kifejezés){ utasítás; } else { utasítás; } Többirányú elágazás: switch(kifejezés<string|int>){ case érték1: utasítás1; <break|goto|return>; case érték2: utasítás2; <break|goto|return>; .. default: utasítás; <break|goto|return>; } Nem úgy mint C/C++ ban itt kötelező a switch-nek a case ágát lezárni, ha van benne utasítás definiálva.
Elágazás utasítás (2) Minden elágazás végére kötelező (nem úgy mint C/C++-ban) a befejező utasítás (break|goto|return) ahol aktuálisan valamilyen utasításokat is közlünk a címke után.
Elágazás utasítás (3) Ha mégis több címkéhez szeretnénk valamilyen aktivitást rendelni, például így tehetjük meg: switch (1) { case 1: case 2: MessageBox.Show("1"); MessageBox.Show("1 és 2"); break; default: break; }
Ciklusok (70-75) While (elöl tesztelős) while(kifejezés igaz){ utasítás; } while(true) {…} // végtelen ciklus Do (hátul tesztelős) do{…}while(kifejezés igaz){utasítás;} do{…}while(false){utasítás} // biztosan egyszer lefut For for(int i =0; i <5; i++){ utasítás1;..} Foreach foreach(azonosító in vektor){ utasítás; }
Ugró utasítások (75-82) break; A legbelső while, do, for utasítást hagyja abba (vagy switchet). continue; Folytatja.. int i = 1; while(true){ i++; if(i<10) continue; // következő ciklusmag if(i==11) break; // Ciklus vége Console.WriteLine(i); } goto címke; NEM AJÁNLOTT, de létezik.
Egyéb utasítások (75-82) Könyvtárak használata using névtér_vagy_osztály vagy using(objektum){utasítások;} Disposable objektumokhoz, pl StreamReader/StreamWriter A kivételkezeléshez is kapcsolódik (később…)
Függvények Érték szerinti paraméter átadás (83) static int maxfv(int a, int b) { return a > b ? a : b; } int c = maxfv(1, 2); MessageBox.Show(c.ToString()); // out: 2 Meg kell említeni hogy alapvetően érték szerinti paraméterátadás van C#-ban. A tömböknél is így van, csak a tömböknek a _címe_ adódik át érték szerint, és gondolom a referenciáknak is, helytakarékosság miatt. De ettől függetlenül nem helyes állítás, hogy C#-ban alapvetően referencia szerinti paraméter átadás van! Megjegyzés: A C++-ban ismert const kulcsszó itt alapvetően érvényben van, mivel érték szerinti átadásról beszélünk alapból. Tehát olyan mintha mindig ott lenne, amíg be nem írjuk a ref-et, vagy out-ot a paraméter elé, ami az jelenti, hogy a paraméterben változás is állhat be, így ezek a const „feloldásai”.
Függvények Rekurzív függvény példa: static int factor(int a) { return ((a <= 1) ? 1 : a * factor(a - 1)); } Érdemes meggondolni hogy milyen adattípussal számolunk/adunk vissza Ez a függvény hamar túllépi az int megengedhető tartományát (exponenciális)!
Függvények Referencia szerinti paraméter átadás (ref) (84. o.) void csere(ref int x, ref int y) { int t = x; x = y; y = t; } int a = 2, b = 3; csere(ref a, ref b); // fontos a ref kulcsszó! MessageBox.Show("{0}, {1}", a, b); // out: 3, 2
Függvények Függvény eredmény paramétere (out) (85) void csere(out int x, out int y) { int t = x; x = y; y = t; } int a = 2, b = 3; csere(ref a, ref b); MessageBox.Show("{0}, {1}", a, b);
Függvények Függvény eredmény paramétere (out) (85) void osszead(int x, int y, out int osszeg) { osszeg = x + y; } int a = 2, b = 3, c = 0; osszead(a, b, out c); MessageBox.Show("{0} ", c); // 5
Függvények Tömbök paraméterben (86) void csere(int []cserelendo) { int t = cserelendo[0]; cserelendo[0] = cserelendo[1]; cserelendo[1] = t; } int[] cserelj = {2, 3}; csere(cserelj); MessageBox.Show("{0}, {1}", cserelj[0], cserelj[1]); // 3, 2 Fontos megemlíteni hogy bár alapvetően érték szerinti átadás van C#-ban, a tömböknek mindig csak a _címe_ adódik át _érték szerint_. Ez azt jelenti hogy a hívó fél számára látszik, hogyha megváltoztatunk valamit egy tömbben.
Függvények Változó számú paraméter átadása (89-91) void csere(params int[] list) { int t = list[0]; list[0] = list[1]; list[1] = t; } Fog-e látszani a csere a hívó fél számára? A válasz a kérdésre: a hívás módjától függ
Függvények Változó számú paraméter átadása Ekkor „rendes” paramétert is megadhatunk, de szigorúan csak a változó számú paraméter definiálása előtt. void rendez(int n, params int[] miket) void rendez(params int[] miket, int n) // hiba
Függvények Függvények túlterhelése (91-92) Cél: Ugyanazt a funckiót ne kelljen máshogy elnevezni, csak mert más típusokra szeretnénk végrehajtani. double maximum(double x, double y) int maximum(int x, int y)
Osztályok (102) Osztályok definiálása class Pont { private int x; // adattagok private int y; public Pont() { // konstruktor } public Pont(int a, int b) { // felüldefiniált konstruktor x = a; y = b;
Osztályok / tulajdonságok (118) class Pont { private int x; public int y; public int X { get { return x; } set { x = value; …. A tulajdonságok CÉLJA, ÉRTELME -> adatelfedés! Adat ellenőrzése mielőtt értéket tudnánk neki adni! Például valamilyen feltételnek megfelelő dolgot tudjunk csak értékül adni… stb. ADATHOZZÁFÉRÉSI TULAJDONSÁGOT definiáljanak.
Osztályok / tulajdonságok (118) class Pont { private int x; // automat. letrejon, nem is kell public int y; public int X { get; set; } // automatikus tulajdonság public Pont() { } public Pont(int a, int b) { x = a; y = b;
Kivétel kezelés (146-153) Alapvetően (a Törtek érettségi feladathoz) int sz1 = 0; // számláló változó try { sz1 = int.Parse(Console.ReadLine()); } catch (Exception) Console.WriteLine("Hiba a beolvasás közben!");
Kivételkezelés (146-153) Ha tudjuk a konkrét hiba típusát. try { sz1 = int.Parse(Console.ReadLine()); } catch (FormatException) Console.WriteLine("A megadott érték felismerhetetlen számként!"); catch (OverflowException) Console.WriteLine("A megadott érték túl nagy/kicsi!"); catch (Exception) { // biztos ami biztos Console.WriteLine("Ismeretlen hiba!"); Megemlíteni hogy a konkrét hibatípusokat láthatjuk, ha a függvény felé húzzuk az egeret. Ott meg szokták adni milyen hibákat tud dobni a függvény.
Kivételkezelés (146-153) int sz1 = 0; try { sz1 = int.Parse(Console.ReadLine()); } catch (Exception) Console.WriteLine("Ismeretlen hiba!"); finally { Console.WriteLine("Ez a blokk biztosan lefut!"); Ez olyan mint a using amit előbb említettünk, miért, az mit csinál?
Kivételkezelés (146-153) checked/unchecked – miért van rá szükség? int a = Int32.MaxValue; // az intek maximum értéke try { a += 1; } catch (OverflowException) Console.WriteLine("'a' értéke túl nagy!"); // nem váltódik ki finally { Console.WriteLine("a: {0}", a); // -2. 147. 483. 647 Megemlíteni hogy az OverflowException az int.Parse vagy convert felett ugye értelmetlen, mert abba már alapból benne van, hogy dobhat ilyen hibát.
Kivételkezelés (146-153) int a = Int32.MaxValue; // maximum érték try { checked a += 1; } catch (OverflowException) Console.WriteLine("'a' értéke túl nagy!"); // kiváltódik! finally { Console.WriteLine("a: {0}", a); // marad Int32.MaxValue Itt a CHECKED megy! Miért? Érdekesség képpen ki lehetne próbálni hogy az előbbiekben említett rekurzív faktor függvény meddig bírja checked nélkül.
Fontosabb String függvények Length – a karakterlánc hossza CompareTo(string) – ha az eredmény 0, akkor azonos Equals(string) – eredmény boolean IndexOf(string) – eredmény egy index v. -1 Insert(int,string) – a második paraméterül kapott szöveget beszúrja az elsőbe, az adott indextől Fontos: Ezek nem módosítják az eredeti karakterláncot, max. visszatérési értékbe adják az újat. Ha mégis ez a cél: StringBuilder.
Fontosabb fv.-ek a Math névtérben Math.Sin(x), Math… // a következők elé mind kell a Math. Cos(x), Tan(x), Exp(x), Log(x), Sqrt(x), Abs(x), Round(x), Ceiling(x), Floor(x), Pow(x,y) Konstansok Math.PI Math.E
További függvények… String Math http://msdn.microsoft.com/en-us/library/system.string.aspx Math http://msdn.microsoft.com/en-us/library/system.math(v=vs.110).aspx
Felhasznált irodalom Illés Zoltán.: Programozás C# nyelven JOS, 2008, Második, átdolgozott kiadás Internetes: http://www.jos.hu (érettségi feladatok) http://msdn.microsoft .com Teljes C# referencia http://msdn.microsoft.com/en-us/library/618ayhy6(v=vs.110)