Session Code: N/A C# Zero.4 Introducing Visual C# 2.0 Fülöp Dávid MCT, MCPD david.fulop@live.com
Témák Mik a problémák a nyelvvel? Hol segít a C# 2.0? Fejlesztett tulajdonságok Statikus és részleges osztályok Generics A delegáltak és a metódusok továbbfejlesztése Anonim metódusok Nullable típusok
PROBLÉMÁK A NYELVVEL
Problémák a C# 1.2-vel Hol nem tud eleget a C# 1.2? Típusbiztos gyűjtemények hiánya A delegate variance hiánya Az értéktípusok nullozhatatlansága A delegáltak... Nos, suták. Az iterátorok nehézkes megírása Hol akadályozhat a munkában a típusrendszer? Statikus nyelvben nincs duck typing
A C# 2.0 ÁTTEKINTÉSE
A C# 2.0 nyelv elhelyezése A C#2 típusrendszere (nem változott) statikus A rendszer mindig pontosan tudja, hogy milyen tagokat használhatunk. explicit Mindig pontosan meg kell adnunk egy tag típusát. Típusbiztos Egy változót nem használhatunk más típusúként hacsak nincs köztük konverziós operátor.
A tulajdonságok fejlődése C#1-ben a get/set örökli a prop. láthatóságát Ha csak olvasható propertyt szeretnénk, törölni kell a setet, ez problémás lehet C#2-ben a get/set accessorok saját láthatóságot kaphatnak A protected set megoldja az öröklésnél felmerült problémákat public int Age { get { return age; } protected set { age = value; } }
Statikus osztályok Egységesül a utility class pattern Sokszor készítettünk segédosztályokat: Az összes tag statikus Az osztály az Objectből származik, sokszor lezárt Legtöbbször nem tárol állapotot Nincs látható konstruktor Alkalmazzuk a static kulcsszót az egész osztályra! Implicit abstract és sealed lesz Nincs őse (de: System.Object), nem valósít meg interfészt Nem tartalmazhat nem-statikus tagokat, operátorokat, protected (internal) láthatóságú tagokat
Részleges osztályok A partial kulcsszó vezeti be Lehet abstract vagy sealed Egy osztály kódja több fájlra oszlik Segíti a kód olvashatóságát A VS designeréhez szükséges kódgenerátorok Az osztály magját legenerálja a VS, a többit mi írhatjuk meg, anélkül, hogy a generált részbe bele kellene nyúlni Fordításkor a compiler egyetlen típust gyárt le a több fájlból
Mi a probléma? class Alma { public bool CreatedByGonoszMostoha; } class AlmaList { private Alma[] items = new Alma[5]; public void Add(Alma item) { //... } public void Remove(Alma item) { //... } public Alma this[int i] { //nem kivételkezelünk... get { return items[i]; } set { items[i] = value; } } }
Mi a probléma? ArrayList aaamáák = new ArrayList(); aaamáák.add(new Alma()); Console.WriteLine(aaamáák[0].GetType()); Console.WriteLine(aaamáák[0].CreatedByGonoszMostoha); Console.WriteLine(((Alma)aaamáák[0]).CreatedByGonoszMostoha);
Típusbizonytalanság Mit tehetünk, ha egy tömbünknek egyszerre kell dinamikusnak és típusbiztosnak lennie? C#1.2: Gyárcsá magadnak! Miért kell egy interfészmetódusnak objectet visszaadnia vagy paraméterként fogadnia? C#1.2: Írjunk meg minden interfészt minden típusra? ROTFLMAO!
Generikus típusok Más néven sablonok, template-ek Olyan osztályok, metódusok, melyek legalább egy típusparaméterrel rendelkeznek Miért előnyös genericset használni? Nagyobb flexibilitás Nagyobb (típus)biztonság Jobb teljesítmény Generikus metódus nem csak generikus osztályban lehet Egy generikus osztály nem kell, hogy generikus metódusokat tartalmazzon
.NET 1-es típus ArrayList Queue, Stack Generikus gyűjtemények HashTable, ListDictionary, HybridDictionary, OrderedDictionary, NameValueCollection SortedList SortedDictionary DictionaryEntry Megfelelő generikus típus List<> Queue<>, Stack<> Dictionary<> SortedList<> SortedDictionary<> NameValuePair<> - LinkedList<>
Generikus és normál gyűjtemények Jon Skeet: C# in Depth
Saját generikus típusok A név után < és > közé jönnek a típusparaméterek Osztály, interfész, struktúra, metódus public class MyGenList<T> { ArrayList al = new ArrayList(); public void Add(T val) { al.add(val); } public TRet GetAs<TRet>(int index) { return al[index] as TRet; }... }
Default érték, megkötések A default kulcsszó Nem tudható, hogy érték vagy referencia típusú-e a paraméter Megoldás: this.elem = default(t); Referenciánál nullt ad vissza, érték típusnál bitenkénti nullát Megkötések A típusparaméterek elvárt viselkedését írják le Alapban annyit tudunk, hogy a típus a System.Objectből származik Típusnál és metódusnál is használhatók A where kulcsszóval vezetjük be A megkötések fajtái Leszármazott Interfész Érték típus Referencia típus (where T : class) Konstruktor (where T : new()) (where T : Személy) (where T : IEnumerable<T>) (where T : struct)
A megkötések megkötései Nem lehetnek a megkötésben Lezárt osztályok Primitív típusok System.Array System.Delegate System.Enum System.ValueType
Megkötések használata class MyClass<T> where T : IEnumerable<T> { public void Iterate(T data) { foreach (object item in data) Console.WriteLine(item); } } class MyClass2<T> where T : new() { T obj = new T();... }
FELADAT
Önálló feladat Saját generikus metódus Készíts egy egyszerű típust Legyen egy duplán paraméterezett metódusa Metódusparaméterek: T*+ list, U comparer A comparer a C#1-ben látott IComparert valósítsa meg A metódus a comparer objektummal rendezze a tömböt, és adja vissza rendezetten. A kapott tömbhöz ne nyúljon! A metódus csak Celeb (és abból leszármazó) tömböket fogadjon el. Használd ki a generikus megkötéseket!
Type inference, generikus variancia Type inference Ha egy metódusparaméterből egyértelmű, hogy milyen típusparaméterrel szeretnénk dolgozni, a fordító kitalálja helyettünk, nem kell explicit módon beírnunk. Paramétertípus-variancia Nincs. (Pont.) Animal[] animals = new Cat[5]; animals[0] = new Animal(); //lefordul, elszáll List<Animal> animals = new List<Cat>(); //elszáll animals.add(new Animal());
Értéktípusok nullértéke C# 1.2-ben Nem lehetséges; a megoldási minták: Magic value Referenciatípusú csomagolóosztály Egy extra bool flag Egyik sem szép, de cserébe legalább rontják a kódot
Nullable típusok Értéktípusok, melyek értéke null is lehet A használat két módja.net: Nullable<értéktípus> Pl.: Nullable<int> i = null; Csak C#: Értéktípus? Pl.: int? i = null; Tulajdonképpen referenciatípusok Nem egyértelmű a Nullable<típus> -> típus átalakítás, kasztolni kell Némileg lassítják a kódot!
A null-coalescing operátor?? (nem, nem felejtettem el a szöveget ) Bináris operátor Ha a baloldal nem null, az lesz a kifejezés értéke, ha null, a jobb oldal lesz. Address contact = user.contactaddress?? order.shippingaddress?? user.billingaddress;
Delegáltak a C# 1.2-ben Megoldandó problémák A szintaxis sokszor feleslegesen bőbeszédű Nincs visszatérésitípus-kovariancia Nincs paramétertípus-kontravariancia
Delegáltak a C# 2.0-ban I. Metóduscsoport-konverzió Egy metódusnév automatikusan delegálttá alakul, ha szükség van rá. Rövidül a kód Ha paraméter, szükség lehet explicit kasztolásra void MyMethod() void MyMethod(object sender, EventArgs e) ThreadStart x = MyMethod; EventHandler y = MyMethod;
Delegáltak a C# 2.0-ban II. Eltűnik a szigorú szignatúra-megkötés Paraméter-kontravariancia Egy paraméter típusának megfeleltethető a típus egy őstípusa is. Visszatérési érték-kovariancia A visszatérési érték típusának megfeleltethető a típus egy leszármazottja is.
Delegáltak a C# 2.0-ban III. Megjelennek a névtelen metódusok A delegate kulcsszóval nyithatók Inline, a használat helyén írjuk meg őket Előnye, hogy elérhetők a helyi változók A paraméterek elhagyhatók button1.click += delegate(object o, EventArgs e) { MessageBox.Show(o.ToString()); }; delegate void Printer(string s); string s = "Hello "; Printer p = delegate(string j) { Console.WriteLine(s + j); }; p("world!"); //Itt adjuk át a j paramétert
FELADAT
Önálló feladat Névtelen metódus Folytasd az előző feladatot Írj egy olyan overloadot a metódusnak, amely IComparer helyett egy metódust fogad, és ennek segítségével rendezi a tömböt. Teszteld a metódust egy névtelen metódus átadásával.
Iterátorok a C# 1.2-ben A foreach-csel való használathoz szükséges A megoldásuk sok kódolást igényel Beágyazott osztály a listánkban, hogy hozzáférjünk a lista belső változóihoz Megvalósítani rajta az IEnumerator interfészt Gondoskodni az állapotinformáció tárolásáról Ez sok kód, tele hibalehetőségekkel A kód logikája legtöbbször ugyanaz sokszor írjuk le ugyanazt
Iterátorok a C# 2.0-ban Megjelenik a yield kulcsszó A megoldás akár egy sorba is belesűríthető Elég az enumerálandó osztály GetEnumerator metódusában megírni a kódot
Amit az iterátorokról tudni érdemes Ha iterálás közben változik a lista, az hiba Érdemes snapshot -ot készíteni a tömbről Érdemes rögtön readonly-vá is tenni Ezzel szálbiztossá is tehetjük az enumerátort Statikus gyűjteményeknél erre nincs szükség
Példafeladat AZ ÁLLATORVOSI LÓ 2.0
Az állatorvosi ló megnevelése Az eddig tanultak alapján, a C# 2.0 eszközeivel készítsük el a Ló osztályt, mely rendelkezik egy névvel, egy születési idővel, egy árral és egy listával az állat eddig begyűjtött díjairól. Legyen továbbá egy eseménye (Versenyez), melyre más objektumok feliratkozhatnak. készítsük el az erre feliratkozó Függő osztályt. készítsünk egy listát a lovakból, és jelenítsük meg őket ábécérendben, valamint listázzuk ki a 10000 kreditnél drágább lovakat. gondoljuk meg, hogyan tudjuk a még ár nélküli lovakat kezelni.
RECAP
Összefoglalás A generics kiegészítette a nyelvet azokkal a részekkel, amelyek kardinálisak a könnyű fejlesztéshez Megoldott az értéktípusok nullozhatósága is A delegáltak fejlesztései egyszerűbb programozást tesznek lehetővé A névtelen metódusokkal kevesebb kóddal, átláthatóbban oldhatunk meg feladatokat Egyéb apróbb fejlesztések is történtek Nagyobb tudású tulajdonságok, statikus és részleges osztályok...
Q & A
C# Zero.4 Introducing Visual C# 2.0 KÖSZÖNÖM A FIGYELMET!