c# zero.4 introducing visual c# 2 · •c#2-ben a get/set accessorok saját láthatóságot...
TRANSCRIPT
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
Generikus gyűjtemények.NET 1-es típus Megfelelő generikus típus
ArrayList List<>
Queue, Stack Queue<>, Stack<>
HashTable, ListDictionary, HybridDictionary, OrderedDictionary, NameValueCollection
Dictionary<>
SortedList SortedList<>
SortedDictionary SortedDictionary<>
DictionaryEntry 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 (where T : Személy)• Interfész (where T : IEnumerable<T>)• Érték típus (where T : struct)• Referencia típus (where T : class)• Konstruktor (where T : new())
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állanimals.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 GetEnumeratormetó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
AZ ÁLLATORVOSI LÓ 2.0Példafeladat
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
KÖSZÖNÖM A FIGYELMET!C# Zero.4 – Introducing Visual C# 2.0