Skip to content
This repository was archived by the owner on Feb 13, 2024. It is now read-only.

Commit 8b9c178

Browse files
authored
Merge pull request #8 from tothpeterdev/chapter3-fix
Chapter 3 fixes
2 parents 21b56a5 + b91f486 commit 8b9c178

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

manuscript/chapter3.adoc

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ A gyakorlat kezdetén töltsük le a [kiinduló projektet](https://github.com/bm
77

88
Megnyitás után tekintsük át a kiinduló projektben levő fájlokat:
99

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.
1111
* *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.
1212
* *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.
1313
* *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 =
121121
d => d.Name.StartsWith(searchText, StringComparison.OrdinalIgnoreCase);
122122
----
123123

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.
125125

126126
Az `Action<>` hasonló elven működik, visszatérési érték nélküli függvényekre.
127127

@@ -213,7 +213,7 @@ Most már használhatjuk azt a szintaxist, mintha a kollekciónak eleve lenne ö
213213
Console.WriteLine($"Életkorok összege: {Dogs.Sum(d => d.Age ?? 0)}");
214214
----
215215

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é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á.
217217

218218
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.
219219

@@ -301,19 +301,19 @@ Próbáljuk ki a legfelső szintű kód elején, válasszuk ki a 2010 előtt sz
301301
/**/IEnumerable<Dog> Dogs = Dog.Repository.Values;
302302
foreach (var text in Dogs
303303
.Where(d => d.DateOfBirth?.Year < 2010)
304-
.Select(d => $"{d.Name} ({d.Age}))"))
304+
.Select(d => $"{d.Name} ({d.Age})"))
305305
{
306306
Console.WriteLine(text);
307307
}
308308
----
309309

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.
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.
311311

312312
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.
313313

314314
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.
315315

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.
317317

318318
== Anonim típusok
319319

@@ -336,7 +336,7 @@ Az anonim típusok:
336336
* típusnevét nem ismerjük, így hivatkozni sem tudunk rá, csak a `var`-t tudjuk használni
337337
* 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
338338

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ó.
340340

341341
TIP: Figyeljük meg, hogy az *IntelliSense* is működik ezekre a típusokra, felkínálja a típus property-jeit.
342342

@@ -351,7 +351,7 @@ A `Contents` tulajdonság típusa a fenti anonim objektumaink tömbje, ezért ne
351351

352352
[source,csharp]
353353
----
354-
var dolog2 = new { Name = "Körte", Weight = 90, Size=12 };
354+
var dolog2 = new { Name = "Körte", Weight = 90, Size = 12 };
355355
----
356356

357357
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;
386386

387387
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.
388388

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<>`.
390390

391391
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.
392392

393393
== Kitekintő: Expression<>, LINQ providerek
394394

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.
396396

397397
[source,csharp]
398398
----

0 commit comments

Comments
 (0)