Kezdőlap > .NET, C#, Linq > Bevezetés a LINQ világába – (2. rész)

Bevezetés a LINQ világába – (2. rész)

2011. június 8. szerda Hozzászólás Go to comments

Az alábbi fejezetek a “Bevezetés a LINQ világába” c. irományomból valóak. Ez egy saját kis jegyzet, reményeim szerint hasznát tudjátok venni. Amiben viszont én kérném a segítségeteket az az, hogy az írást javítsátok. Ha fogalmazási, stilisztikai vagy esetleg tartalmi hibát vélnétek felfedezni kérlek írjátok meg a kommentek között.
Segítségetek előre is köszönöm.

Ahhoz, hogy értsük, hogy mi és miért született meg a nyelvben, illetve hogy ezeket később rendeltetésszerűen használjuk, nézzük át a C# 3.0-nak az újdonságait.

C# 3.0 újdonságai

A C# 3.0 -ban többek között az alábbi újdonságok jelentek meg:

  • Automatikus tulajdonságok
  • Implicit típusú lokális változók
  • Bővítő metódusok
  • Objektumok és gyűjtemény-inicializálók
  • Lambda kifejezések
  • Anonymous típusok

Miután elkezdtük használni a LINQ-t, látni fogjuk, hogy mennyi helyen is használjuk fel ezeket az újdonságokat. Hisz az első pillanatban, amikor olvassuk, illetve tapasztaljuk őket, felmerülhet a kérdés, hogy miért kellett ez a nyelvnek; de a végén, amikor már komplexebb linq kifejezéseket is írunk, kikristályosodik, hogy ezeknek a nyelvi újításoknak mégis mi a létjogosultsága.

Nézzünk meg néhány fontosabb újdonságot közelebbről.

Automatikus tulajdonságok

Szinte minden osztálynál készítünk tulajdonságokat, mégis elég hosszadalmas gépelést kell elvégeznünk ahhoz, hogy mi egy property-t létrehozzunk. Pl. az alábbi ábra bal oldalán a korábbi módszer látható, míg a jobb oldalon az új, automatikus tulajdonság. Tehát az automatikus tulajdonság segítségével sokkal egyszerűbben tudunk létrehozni egy-egy property-t.

image

Látható, hogy most már nem kell külön kiírni a getter és a setter részt. Ha egyszerű tulajdonságról van szó, elég csak get-et és set-et írni, a fordító a háttérben úgyis legenerálja a bal oldali kifejezést. Ha csak olvashatóvá szeretnénk tenni a tulajdonságot, akkor a set kulcsszó elé írjunk a private kulcsszót. Fontos, hogy a get és/vagy a set rész nem hagyható le!

Amennyiben Visual Studio-t használunk, és gyorsan szeretnénk egy új automatikus tulajdonságot létrehozni, írjuk be a prop szót, majd kétszer egymás után nyomjuk le a Tab billentyűt.

Implicit típusú lokális változók

Ennek a nyelvi újdonságnak a segítségével immár nem kell kiírnunk a változó típusát (ha annak már van értéke)

Például eddig, ha egy változót deklaráltunk, akkor az így nézett ki:

int i = 10;

string s = "alma";

List<Char> chList = new List<char>();

Exception e = new Exception();

Mostantól viszont elég a bal oldali kifejezés elé a var kulcsszót kiírni.

var i = 10;

var s = "alma";

var chList = new List<char>();

var e = new Exception();

A fordító ugyanis megállapítja, hogy mi van a kifejezés jobb oldalán, és annak a típusával helyettesíti be a bal oldalt.

Ezzel első ránézésre megint csak időt spórolunk, hisz most már nem kell kiírni, hogy List<Char>, vagy egyéb bonyolultabb típusneveket, hanem elég csak a var kulcsszóval ellátni, ami csak 3 karakter. De ne gondoljuk azt, hogy ez a var olyan, mint amit más fejlesztők a JavaScriptben megszokhattak. Azaz, ha van egy var i = 1; kifejezés, és hirtelen azt mondjuk, hogy i=”béka”, akkor a fordító rögtön szólni fog, hogy ezt mi nem tehetjük meg, hisz az i típusa int, amit hirtelen nem alakíthatunk át string-gé. Tehát ettől a var szótól még ugyanúgy típusos a nyelv, csak a szintaktika lett kicsit lazább.

Persze a var-t ne használjuk mindig, minden körülmény között, mert a kódolvashatóságot bizony ronthatja. Viszont látni fogjuk, hogy nélküle a Linq-t elég nehézkes lenne kezelni. Gondoljunk egy olyan esetre, amikor egy adatbázisban olyan összetett lekérdezést csinálunk, amely típusának a megállapítása nem triviális ― ilyenkor a var használata erősen javallott.

Bővítő metódusok

A bővítő metódusok segítségével meglévő osztályokat tudunk kiterjeszteni, származtatás nélkül!

Hogy elképzeljük, miért is jó ez, nézzük meg az alábbi példát.

Tegyük fel, hogy van egy A osztályunk. Szeretnénk kibővíteni a képességeit azáltal, hogy megírunk egy-két plusz függvényt hozzá. Ha nem tudunk hozzáférni az A osztály kódjához, mert mondjuk csak egy DLL-ben áll rendelkezésünkre, akkor az objektum-orientált paradigma szerint a természetes lépés az, hogy származtatunk belőle egy B osztályt, és odapakoljuk az új függvényeinket.

Na de mi történik akkor, ha az osztályt a készítője ellátta a sealed kulcsszóval? Akkor bizony nincs származtatás! Nem hagytak nekünk más választást, mint szögre akasztani OO imageelveinket, és kétségbeesésünkben definiálni egy statikus osztályt, amiben elhelyezzük a statikus függvényeinket, melyek paraméterként kaphatják az A osztály egy példányát. Érezzük, hogy ez minden, csak nem az igazi. Nem kapcsolódik a függvényünk az osztályhoz, senki más nem fog tudni a függvényeinkről, csak mi (nincs intellisense se) stb. Pedig nem járunk messze a megoldástól, első pillantásra a bővítő függvények is valami ilyesmit csinálnak.

Bővítő metódus létrehozásának lépései:

  1. Publikus statikus függvény, statikus osztályban
  2. Az első paraméter a bővítendő osztály típusa
  3. Megelőzi a ”this” kulcsszó
  4. Csak publikus adattagokhoz fér hozzá

image

Bővítő függvények készítésekor az első paramétert megelőzi a this kulcsszó, ezzel jelezvén, hogy az első paraméterként megjelölt típus nem más, mint az a típus, amit kiterjeszt!

A compiler fordításkor átnézi az összes statikus osztályt bővítő függvények után kutatva, és fordítási időben elvégzi a szükséges kiterjesztéseket. Érték- és referencia-típusokat is egyaránt bővíthetünk. Az ajánlás szerint érdemes egy külön namespace-ben egy statikus osztályba pakolni az ilyen bővítő függvényeket, és inkább usingolni a namespace-t a projektünkben.

Maga a System.Linq névteret is, ha usingoljuk, a tömbök extra funkcionalitást kapnak tőle. Tudunk rájuk szűrni egyszerűen, aggregációkat végezhetünk, stb. Gondoljunk csak bele, hogy új funkcionalitással látnánk el egy eddig megírt osztályt, de valahogy úgy, hogy ne írjunk a kódjába, hisz problémát okozhat a visszafelé kompatibilitás. Ugyanez volt a .NET esetén is. Csináljunk új funkciókat, amire szüksége lehet a fejlesztőknek. Igen ám, de ha belepiszkálunk a kódba, akkor új verziót kell kiadni, és az visszafelé nem lesz kompatibilis. Erre is tökéletes megoldást nyújthatnak a bővítő metódusok.

A LINQ is ennek tudatában működik, hisz ha írunk egy Linq kifejezést, azt a compiler fordítási időben bővítő metódusokká alakítja.

Az alábbi ábra is ezt a folyamatot szemlélteti. Látható még, hogy ennél az egy kifejezésnél mennyi nyelvi újítást használ fel a rendszer.

image

A C# 3.0-nak még rengeteg olyan újdonsága van, ami a Linq miatt került a nyelvbe, ezekkel és a Linq-val a következő fejezetben foglalkozunk.

Kategóriák:.NET, C#, Linq Címke: , , ,
  1. 2011. június 8. szerda - 10:16

    És a végén majd bedobod a komplett jegyzetet is?

    Morzel

    • 2011. június 8. szerda - 10:18

      Igen. Össze szedem a fejezetek / alfejezetek észrevételeit. Kijavítom és kidobom azt is.

  2. martonx
    2011. június 9. csütörtök - 08:07

    Nagyon hasznos anyag, örömmel olvasom!
    Köszi!

  3. 2011. június 9. csütörtök - 10:03

    Szerintem hibás a kép. Az alsó képen Length.StartsWith helyett Title.StartsWith-nek kellene szerepelnie ha jól sejtem.

    • 2011. június 9. csütörtök - 10:07

      Észre se vettem. Kösz. Javítom.

  4. reiteristvan
    2011. június 9. csütörtök - 10:50

    Előre látom, hogy a fényképemet darts táblára ragasztod :D, de azért itt a következő adag javítás:

    “Ahhoz, hogy értsük, hogy mi és miért született meg a nyelvben, illetve hogy ezeket később rendeltetésszerűen használjuk, nézzük át a C# 3.0-nak az újdonságait.”

    Ezt az első résznél már megírtam.

    “C# 3.0 újdonságai

    A C# 3.0 -ban többek között az alábbi újdonságok jelentek meg:”

    Felesleges az alcím után még egyszer leírni ugyanazt, illetve ezek nem exkluzíve a C# 3.0-ra vonatkoznak, a VB.NET-ben ugyanúgy ott vannak.
    Még annyit, hogy az alcím után lehetne egy üres sor, így olyan zsúfoltnak tűnik.

    “Hisz az első pillanatban, amikor olvassuk, illetve tapasztaljuk őket, felmerülhet a kérdés, hogy miért kellett ez a nyelvnek;”

    “Hisz'” után aposztróffal jelezzük a rövidítést, igazából mondat elején szebb lenne a “hiszen”. A “miért kellett ez a nyelvnek” kicsit kellemetlen hangzású, nem a nyelvnek kell, az nem élőlény, előnyösebb lenne a “miért tették bele a fejlesztők a nyelvbe” forma.

    “Szinte minden osztálynál készítünk tulajdonságokat, mégis elég hosszadalmas gépelést kell elvégeznünk ahhoz, hogy mi egy property-t létrehozzunk.”

    A “gépelést kell elvégeznünk” nagyon csúnya, helyette “hosszadalmasan kell gépelnünk” szebb. A mondat második felében felesleges még egyszer rámutatni arra, hogy egy tulajdonsággal van dolgunk, még akkor is ha nincs szóismétlés.

    “Pl. az alábbi ábra bal oldalán a korábbi módszer látható, míg a jobb oldalon az új, automatikus tulajdonság.”

    Mondat elején ne használjunk “Pl.”-t, ha nagyon muszáj akkor teljesen legyen kiírva. A fönti mondat egyébként sokkal jobban hangzik nélküle.

    “Tehát az automatikus tulajdonság segítségével sokkal egyszerűbben tudunk létrehozni egy-egy property-t.”

    Nem szerencsés a “Tehát” használata a mondat elején, azt jelzi, hogy előtte leírtál olyan tényeket, amelyek alapján erre a következtetésre jutottál, ez viszont ebben az esetben nem történt meg. Írd oda, hogy “a képen jól látszik, hogy mennyivel tisztább az automatikus property definíció”, vagy valami ilyesmit.

    “Fontos, hogy a get és/vagy a set rész nem hagyható le!”

    Az “és/vagy” eléggé ellentmondó, mindkettő kell.

    “Például eddig, ha egy változót deklaráltunk, akkor az így nézett ki:”

    Megint nincs szükség a “Például”-ra.

    “Mostantól viszont elég a bal oldali kifejezés elé a var kulcsszót kiírni.”

    Nem pontos. A típusnév helyére kell a var-t írni.

    “A fordító ugyanis megállapítja, hogy mi van a kifejezés jobb oldalán, és annak a típusával helyettesíti be a bal oldalt.”

    Dettó. A bal oldal típusáról van még mindig szó. Egyébként nem feltétlenül a fordító teszi ezt meg, ha a forrás írása alatt a var felé viszed az egeret rögtön kiírja a típust. Inkább arra tippelnék, hogy az előfordító szépen a megfelelő formára hozza a forrást.

    “akkor az objektum-orientált paradigma szerint a természetes lépés az, hogy származtatunk belőle egy B osztályt, és odapakoljuk az új függvényeinket.”

    Nana. Azért mert OO módszerrel programozunk egyáltalán nem természetes, hogy nyakra-főre származtassunk. Egész sor olyan tervezési minta van ami a fenti probléma megoldására született.

    “Na de mi történik akkor, ha az osztályt a készítője ellátta a sealed kulcsszóval? Akkor bizony nincs származtatás! ”

    Általában a sealed módosító a legkisebb probléma, nem véletlenül szokták oda tenni.

    “Nem hagytak nekünk más választást, mint szögre akasztani OO elveinket, és kétségbeesésünkben definiálni egy statikus osztályt, amiben elhelyezzük a statikus függvényeinket, melyek paraméterként kaphatják az A osztály egy példányát.”

    Semmit nem kell szögre akasztani, nagyon szép OO megoldások léteznek ilyen helyzetekre: tervminta, tervminta, tervminta…

    “Érezzük, hogy ez minden, csak nem az igazi. Nem kapcsolódik a függvényünk az osztályhoz, senki más nem fog tudni a függvényeinkről, csak mi (nincs intellisense se) stb. Pedig nem járunk messze a megoldástól, első pillantásra a bővítő függvények is valami ilyesmit csinálnak.”

    Pontosan ugyanezt csinálják a bővítő metódusok, éppen csak van hozzá IntelliSense támogatás.

    “Bővítő metódus létrehozásának lépései:
    Publikus statikus függvény, statikus osztályban
    Az első paraméter a bővítendő osztály típusa
    Megelőzi a ”this” kulcsszó
    Csak publikus adattagokhoz fér hozzá”

    Az utolsó nem lépés, az a metódus tulajdonsága.

    “A compiler fordításkor átnézi az összes statikus osztályt bővítő függvények után kutatva, és fordítási időben elvégzi a szükséges kiterjesztéseket. Érték- és referencia-típusokat is egyaránt bővíthetünk. Az ajánlás szerint érdemes egy külön namespace-ben egy statikus osztályba pakolni az ilyen bővítő függvényeket, és inkább usingolni a namespace-t a projektünkben.”

    Ez volt az a bekezdés, ami egy kicsit megemelte a vérnyomásom. A compiler helyett megteszi a fordító, és egészen nyilvánvaló, hogy a műveletet fordítási időbe hajtja végre, ezt felesleges volt így leírni. “Namespace” helyett is mindenki számára érthető a névtér.

    Most jön az “érdekes” rész: “usingolni a namespace-t”. Ezt egyszerűen nem hiszem el, hogy így leírtad. Esetleg nem lehetett volna azt írni, hogy “felhasználjuk a névteret”? Még ha lenne valamiféle angol megfelelője (usinging??)… Egy ilyen mondatot maximum egy tizenöt éves “3D-s OS-t akarok írni” vérpistikétől várna az ember, nem egy MVP-től.

    Ha valaminek van szép magyar neve akkor használd azt. Egy tonna olyan kifejezés van amit nem lehet rendesen magyarítani (pl. delegate), de amit mégis azt ne erőszakoljuk már meg.

    “A LINQ is ennek tudatában működik, hisz ha írunk egy Linq kifejezést, azt a compiler fordítási időben bővítő metódusokká alakítja.”

    Ezt már az első résznél is akartam írni: most akkor LINQ vagy Linq? Csak az egyiket használd.

    “A C# 3.0-nak még rengeteg olyan újdonsága van, ami a Linq miatt került a nyelvbe, ezekkel és a Linq-val a következő fejezetben foglalkozunk.”

    Azt hittem ezzel ez a fejezet foglalkozik. Eleve nem értem, hogy miért az auto-property-vel kezdted, amikor annak aztán végképp semmi köze a LINQ-hoz (jó, azért valamennyi van, de nem létfontosságú). Hol maradnak a lambda kifejezések amikre lényegében az egész épül?

  5. 2011. június 9. csütörtök - 11:26

    Én azt hiszem, sokan hálásak lehetnek, hogy Attila megírta ezeket a cikkeket és nem a hibákat kellene benne keresni, főleg nem ilyen szőrszálhasogató formában. Annyira frenetikus és bő a magyar szakirodalom, valószínűleg tele van a LINQ (vagy netán Linq, linQ, LinQ?) és a C# 3.0 leírásaival… Mellesleg én kimondottan örülök, hogy nem fordítunk le mindent, éles környezetben, amikor magadnak oldasz meg problémákat, kicsi az esélye, hogy pont magyar leírást fogsz találni az adott problémára, így jó, ha ismered eredeti nyelven (nem beszélve arról, ha egyetemen vesz fel valaki technológiai tárgyat, ott is az esetek nagy részében eredeti nyelven kérdeznek rá vizsgában). Ahány szerző, annyi féle stílus, még jó, hogy nem fogalmazunk mindannyian ugyanúgy. A Silverlight könyvet is sokan írtuk, még sem tépi szét magát attól, hogy mindenki más karakterisztikát képvisel. Furcsa, nyakatekert mondatok pedig mindenkinél előfordulnak, az ok, amiért bent maradnak a végleges cikkben is, talán az, hogy az ember önszorgalmából blogol és nem sok ideje van átnézni, főleg nem átnézetni az összes bejegyzést másokkal. Így a hibák egy része bent marad… illetve az is lehetséges ok, hogy nem csinált egyikünk sem másoddiplomát magyar nyelvből. Ha pedig valakinek mégis szabadon kell engednie a kommentjeit, különben a világ egyensúlya felborul, akkor azt tegye privát üzenetben és ne járassa le a szerzőt.

  6. reiteristvan
    2011. június 9. csütörtök - 13:16

    “Ha pedig valakinek mégis szabadon kell engednie a kommentjeit, különben a világ egyensúlya felborul, akkor azt tegye privát üzenetben és ne járassa le a szerzőt.”

    Tessék szépen megnézni az oldal tetejét:

    “Ha fogalmazási, stilisztikai vagy esetleg tartalmi hibát vélnétek felfedezni kérlek írjátok meg a kommentek között.”

    Erre van egy nagyon csúnya, ám velős mondás: ha k*rva vagy ne csodálkozz, ha megb*sznak. Mindannyian akik blogolunk bevállaljuk azt, hogy esetleg kijavítanak.

    “Annyira frenetikus és bő a magyar szakirodalom, valószínűleg tele van a LINQ (vagy netán Linq, linQ, LinQ?) és a C# 3.0 leírásaival…”

    Tulajdonképpen ez pontosan így van, annak idején amikor a C# 3.0 kijött átlag hetente jöttek ki ilyen cikkek.

    “Mellesleg én kimondottan örülök, hogy nem fordítunk le mindent”

    “Furcsa, nyakatekert mondatok pedig mindenkinél előfordulnak, az ok, amiért bent maradnak a végleges cikkben is, talán az, hogy az ember önszorgalmából blogol és nem sok ideje van átnézni, főleg nem átnézetni az összes bejegyzést másokkal.”

    Nem ez volt a problémám, én is azt mondom, hogy nem kell mindent lefordítani, de szavakat sem kéne kitalálni. Te olvastál már bármely – akár nem magyar nyelvű – szakirodalomban olyat, hogy “usingolom a namespacet”. Mutass egyetlenegyet! Nem is arról van szó, hogy nem lehet szabadon értelmezni az írói szabadságot, de most nem is egy átlag bloggerről van szó, hanem egy számos minősítéssel, díjjal rendelkező szakértőről meglehetősen nagy olvasótáborral. Igenis felelőssége, hogy olyan munka kerüljön ki a kezei közül ami ennek megfelel.

    Nem mellesleg: ha önszorgalomból is blogol, akkor is vegye a fáradtságot, hogy átnézi, ez nem elfogadható kifogás.

    “A Silverlight könyvet is sokan írtuk, még sem tépi szét magát attól, hogy mindenki más karakterisztikát képvisel.”

    Nem is tudom, az én fejezeteimet kijavította egy nyelvi lektor és István is több javítást eszközölt, mégsem kaptam agybajt… Nem a stílusról van szó továbbra sem.

  1. No trackbacks yet.

Vélemény, hozzászólás?

Adatok megadása vagy bejelentkezés valamelyik ikonnal:

WordPress.com Logo

Hozzászólhat a WordPress.com felhasználói fiók használatával. Kilépés / Módosítás )

Twitter kép

Hozzászólhat a Twitter felhasználói fiók használatával. Kilépés / Módosítás )

Facebook kép

Hozzászólhat a Facebook felhasználói fiók használatával. Kilépés / Módosítás )

Google+ kép

Hozzászólhat a Google+ felhasználói fiók használatával. Kilépés / Módosítás )

Kapcsolódás: %s

%d blogger ezt kedveli: