You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Feb 13, 2024. It is now read-only.
Copy file name to clipboardExpand all lines: manuscript/chapter3.adoc
+10-10Lines changed: 10 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ A gyakorlat kezdetén töltsük le a [kiinduló projektet](https://github.com/bm
7
7
8
8
Megnyitás után tekintsük át a kiinduló projektben levő fájlokat:
9
9
10
-
* *Program.cs*: a legfelső szintű kódot tartalmazó osztály. Található benne egy `dogs` változó, ami a `Dog` osztály statikus `Repository` tulajdonságába hív át.
10
+
* *Program.cs*: a legfelső szintű kódot tartalmazó osztály. Található benne egy `Dogs` változó, ami a `Dog` osztály statikus `Repository` tulajdonságába hív át.
11
11
* *Dog.cs*: a korábbi gyakorlatokon használt adatmodell (apróbb módosításokkal). Bekerült egy `Siblings` tulajdonság, a `ToString` pedig kiírja a kutyához tartozó testvérek számát is (ehhez a `TrimPad` bővítő metódust használja). A statikus `Repository` tulajdonság mögött egy lustán inicializált `Lazy<T> RepositoryHolder` található, ami egy megfelelően formázott bemeneti CSV fájlból elkészíti számunkra az adatmodellt, amivel a későbbiekben dolgozunk. Ennek implementációját elég a gyakorlat végén megnézni. Az `Import` és `Export` függvények a kutyák sorosítását végzik el mindkét irányban.
12
12
* *Extensions/StringExtensions.cs*: ez az osztály tartalmaz egy segédmetódust a formázott kiíráshoz. A `Dog` `ToString` metódusa használja fel. A bővítő metódusos részben lesz jelentősége.
13
13
* *dogs.csv*: egy pontosvesszővel tagolt adathalmaz, amelyben 100 darab előre felvett kutya adata található. Innen puskázhatunk, ha ellenőrizni akarjuk, hogy helyesek-e a programunk eredményei.
@@ -121,7 +121,7 @@ Func<Dog, bool> dogFunc =
121
121
d => d.Name.StartsWith(searchText, StringComparison.OrdinalIgnoreCase);
122
122
----
123
123
124
-
A `dogfunc` és a `predicate` kompatibilisnek tűnhetnek (elvégre a jobboldaluk ugyanaz), ám ha lecserélnénk pl. a `ListDogsByPredicate(Dogs, predicate)` hívásban a `predicate`-et `dogFunc`-ra, a kód nem fordulna, ugyanis a két delegáttípus nem kompatibilis.
124
+
A `dogFunc` és a `predicate` kompatibilisnek tűnhetnek (elvégre a jobboldaluk ugyanaz), ám ha lecserélnénk pl. a `ListDogsByPredicate(Dogs, predicate)` hívásban a `predicate`-et `dogFunc`-ra, a kód nem fordulna, ugyanis a két delegáttípus nem kompatibilis.
125
125
126
126
Az `Action<>` hasonló elven működik, visszatérési érték nélküli függvényekre.
127
127
@@ -213,7 +213,7 @@ Most már használhatjuk azt a szintaxist, mintha a kollekciónak eleve lenne ö
WARNING: A bővítő metódusok semmilyen módon nem bontják meg a típusok egységbezárási képességeit. A függvény implementációja a bővítendő típusok kívülről is elérhető függvényeit, propertyjeit használhatják, privát adattagokhoz, függvényekhez nem férnek hozzá.
216
+
WARNING: A bővítő metódusok semmilyen módon nem bontják meg a típusok egységbezárási képességeit. A függvények implementációi a bővítendő típusok kívülről is elérhető függvényeit, propertyjeit használhatják, privát adattagokhoz, függvényekhez nem férnek hozzá.
217
217
218
218
WARNING: A bővítő metódusok alkalmazásakor nagyon fontos, hogy bár a bővítő metódus osztályának nevét nem írjuk ki, az osztály nevének feloldhatónak kell lennie, azaz az osztály névterét `using` direktívával be kell hivatkoznunk. Egy próba erejéig kommentezzük ki a `using HelloLinq.Extensions.Enumerable;` sort és ellenőrizzük, hogy nem fordul a kódunk, a bővítő metódus nevét a fordító nem tudja feloldani.
219
219
@@ -301,19 +301,19 @@ Próbáljuk ki a legfelső szintű kód elején, válasszuk ki a 2010 előtt sz
TIP: a `yield return` egy hasznos eszköz, ha IEnumerable-t kell produkálnunk visszatérési értékként. Segítségével mindig csak akkor állítjuk elő a következő elemet, amikor a hívó kéri. A működését debuggerrel is figyeljük meg: tegyünk breakpointot a két `yield return` sorra, majd kbd:[F10]-zel kövessük végig, ahogy a `foreach` elkéri a `Select`-től a következő elemet, ami emiatt elkéri a `Where`-től, majd újraindul a ciklus. A hívások állapotgépként működnek, a következő meghíváskor onnan folytatódnak, ahonnan az előző `yield return`-nél kiléptünk.
310
+
TIP: A `yield return` egy hasznos eszköz, ha IEnumerable-t kell produkálnunk visszatérési értékként. Segítségével mindig csak akkor állítjuk elő a következő elemet, amikor a hívó kéri. A működését debuggerrel is figyeljük meg: tegyünk breakpointot a két `yield return` sorra, majd kbd:[F10]-zel kövessük végig, ahogy a `foreach` elkéri a `Select`-től a következő elemet, ami emiatt elkéri a `Where`-től, majd újraindul a ciklus. A hívások állapotgépként működnek, a következő meghíváskor onnan folytatódnak, ahonnan az előző `yield return`-nél kiléptünk.
311
311
312
312
Nem nagy meglepetés, hogy az általunk megírt `Sum`, `Average` (melyek egyedi visszatérésűek), `Select` és `Where` (amik szekvenciális visszatérésűek, generátorok) metódusok mind a .NET keretrendszer részét képezik (a https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable[`System.Linq.Enumerable`] statikus osztályban definiált bővítő metódusok). A *LINQ* -- **L**anguage **IN**tegrated **Q**uery -- ezeket a műveleteket teszi lehetővé `IEnumerable` interfészt megvalósító objektumokon. A LINQ függvények bővítő metódusként lettek hozzáadva meglevő funkcionalitáshoz (kollekciókhoz, lekérdezésekhez), sőt, külső library-k is adnak saját LINQ bővítő metódusokat.
313
313
314
314
Cseréljük le a *Program.cs*-ben a `using HelloLinq.Extensions.Enumerable` hivatkozást `using System.Linq`-re: az általunk megírt kód továbbra is ugyanazt az eredményt produkálja! Nézzük meg, hogy hol vannak definiálva ezek a függvények a keretrendszeren belül: a kurzort tegyük a kódban oda, ahol valamelyik korábban megírt függvényünket hívnánk, majd nyomjunk kbd:[F12]-t. Próbáljuk ki, hogy továbbra is az elvárt módon működik-e a programunk.
315
315
316
-
TIP: A névtércsere helyett bekapcsolhatjuk a globális implicit névtér funkciót, mert a *System.Linq* névtér is egy implicit hivatkozott névtér. Ehhez a projektfájlban a `<ImplicitUsings>disable</ImplicitUsings>` beállítást írjuk át `enable`-re, majd a `using HelloLinq` -en kívül minden névtérhivatkozást törljünk a *Program.cs*-ből.
316
+
TIP: A névtércsere helyett bekapcsolhatjuk a globális implicit névtér funkciót, mert a *System.Linq* névtér is egy implicit hivatkozott névtér. Ehhez a projektfájlban az `<ImplicitUsings>disable</ImplicitUsings>` beállítást írjuk át `enable`-re, majd a `using HelloLinq` -en kívül minden névtérhivatkozást töröljünk a *Program.cs*-ből.
317
317
318
318
== Anonim típusok
319
319
@@ -336,7 +336,7 @@ Az anonim típusok:
336
336
* típusnevét nem ismerjük, így hivatkozni sem tudunk rá, csak a `var`-t tudjuk használni
337
337
* nem használhatók ott, ahol a `var` típus se használható, többek között nem adhatjuk át függvénynek és nem lehet visszatérési érték sem
338
338
339
-
Ha az egeret a `var` kulcsszavak, vagy egyes tulajdonságnevek fölé visszük, láthatjuk, hogy valóban fordítási idejű típusokról van szó.
339
+
Ha az egeret a `var` kulcsszavak vagy egyes tulajdonságnevek fölé visszük, láthatjuk, hogy valóban fordítási idejű típusokról van szó.
340
340
341
341
TIP: Figyeljük meg, hogy az *IntelliSense* is működik ezekre a típusokra, felkínálja a típus property-jeit.
342
342
@@ -351,7 +351,7 @@ A `Contents` tulajdonság típusa a fenti anonim objektumaink tömbje, ezért ne
351
351
352
352
[source,csharp]
353
353
----
354
-
var dolog2 = new { Name = "Körte", Weight = 90, Size=12 };
354
+
var dolog2 = new { Name = "Körte", Weight = 90, Size = 12 };
355
355
----
356
356
357
357
TIP: Ha végeztünk az anonim típusokkal való ismerkedéssel, az ezekkel kapcsolatos kódsorokat kikommentezhetjük.
@@ -386,13 +386,13 @@ using HelloLinq.Extensions;
386
386
387
387
A query szintaxis végül a korábban is használt, ún. __fluent szintaxis__sá fordul. Ennek igazolására nézzük meg kbd:[F12]-vel, hogy hol vannak definiálva az újonnan megismert operátorok (`select`, `where`). A két szintaxist szokás ötvözni is, jellemzően akkor, ha query szintaxisban írjuk a lekérdezést, és a hiányzó funkcionalitást fluent szintaxissal pótoljuk.
388
388
389
-
NOTE: A fluent szintaxis olyan kialakítású API-knál alkalmazhatjuk, ahol a függvények a tartalmazó típust várják (egyik) bemenetként és azonos (vagy leszármazott) típust adnak vissza. A LINQ-nél ez a típus az `IEnumerable<>`.
389
+
NOTE: A fluent szintaxist olyan kialakítású API-knál alkalmazhatjuk, ahol a függvények a tartalmazó típust várják (egyik) bemenetként és azonos (vagy leszármazott) típust adnak vissza. A LINQ-nél ez a típus az `IEnumerable<>`.
390
390
391
391
Ezen az órán memóriabeli adatforrásokkal dolgoztunk (konkrétan a `Dogs` nevű `Dictionary<,>` típusú változóval), a LINQ operátorok közül a memóriabeli listákon dolgozókat használtuk, melyeket az `IEnumerable<>` interfészre biggyesztettek rá bővítő metódusként. Ezt a LINQ API-t teljes nevén __LINQ-to-Objects__nek hívják, de gyakran csak LINQ-ként hivatkozzák.
392
392
393
393
== Kitekintő: Expression<>, LINQ providerek
394
394
395
-
Vegyük az alábbi nagyon egyszerű delegate-et és ennek `Expression<>`-s párját.
395
+
Vegyük az alábbi nagyon egyszerű delegate-et és ennek `Expression<>`-ös párját.
0 commit comments