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/chapter4.adoc
+12-12Lines changed: 12 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,15 +1,15 @@
1
1
[#csharp4]
2
2
= C# alapok IV.
3
3
4
-
Ezen a gyakorlaton több különféle nyelvi konstrukciót tekintünk át, vegyesfelvágott jelleggel. Az egyes fő témaköröket külön projektként dolgozzuk ki. A projekteket hozzáadhatjuk az elsőként létrehozott projekt solutionjéhez (menu:jobbklikk a projekten[Add > New project]). Hozzáadás után ne felejtsük el átállítani a futtatandó projektet: menu:jobbklikk a projekten[Set as Startup Project].
4
+
Ezen a gyakorlaton több különféle nyelvi konstrukciót tekintünk át, vegyesfelvágott jelleggel. Az egyes fő témaköröket külön projektként dolgozzuk ki. A projekteket hozzáadhatjuk az elsőként létrehozott projekt solutionjéhez (menu:jobbklikk a solution-ön[Add > New project]). Hozzáadás után ne felejtsük el átállítani a futtatandó projektet: menu:jobbklikk a projekten[Set as Startup Project].
5
5
6
6
== Bejárási problémák
7
7
8
8
Enumerátorok használata esetén két alapvető problémába ütközünk: az egyik a mögöttes kollekció módosulása bejárás során, a másik pedig a késleltetett kiértékelésből adódó mellékhatások kezelése.
9
9
10
10
=== Kollekció módosulása bejárása során
11
11
12
-
Szűrjünk le egy szám-szám szótárat csak azokra az elemekre, amik megfelelnek egy feltételnek, és ezeket távolítsuk el a szótárból!
12
+
Szűrjünk le egy számokat tartalmazó kollekciót csak azokra az elemekre, amik megfelelnek egy feltételnek, és ezeket távolítsuk el a kollekcióból!
13
13
14
14
[source,csharp]
15
15
----
@@ -72,12 +72,12 @@ Ezzel a megközelítéssel futásidőben is állíthatunk össze egy időben vá
72
72
73
73
Töltsünk le egy HTML oldalt, és ezen a problémán keresztül bemutatjuk az aszinkron programozási modellt. A `HttpClient` működésének a részletesebb ismertetése most nem téma, csak a legalapvetőbb funkciókat fogjuk használni.
74
74
75
-
A fő gond, hogy a hosszan futó műveletek blokkolhatják a fő/UI/aktuális szál futását, mindez kliens alkalmazások esetében úgy jelentkezik, hogy nem lesz a alkalmazásunk reszponzív a felhasználói bemenetekre; szerveralkalmazások esetében pedig az adott kérést kiszolgáló szál feleslegesen blokkolódik, amikor esetleg mással is tudna foglalkozni.
75
+
A fő gond, hogy a hosszan futó műveletek blokkolhatják a fő/UI/aktuális szál futását, mindez kliens alkalmazások esetében úgy jelentkezik, hogy nem lesz az alkalmazásunk reszponzív a felhasználói bemenetekre; szerveralkalmazások esetében pedig az adott kérést kiszolgáló szál feleslegesen blokkolódik, amikor esetleg mással is tudna foglalkozni.
76
76
77
-
Ötlet a hosszan tartó műveleteket végezzük aszinkron módon, és ha az befejeződött az eredményről valamilyen módon értesüljünk. A keretrendszer többféle mintát kínál erre: Asynchronous Programming Model (APM), Event-based Asynchronous Pattern (EAP), Task-based Asynchronous Pattern (TAP). Mi most a legutóbbival foglalkozunk csak, a többi jórészt elavultnak számít ma már.
77
+
Ötlet: a hosszan tartó műveleteket végezzük aszinkron módon, és ha az befejeződött az eredményről valamilyen módon értesüljünk. A keretrendszer többféle mintát kínál erre: Asynchronous Programming Model (APM), Event-based Asynchronous Pattern (EAP), Task-based Asynchronous Pattern (TAP). Mi most a legutóbbival foglalkozunk csak, a többi jórészt elavultnak számít ma már.
78
78
79
79
A TAP-ra már C# nyelvi támogatást is kapunk az `async`/`await` kulcsszavakon keresztül.
80
-
Vegyünk fel egy új metódust és hívjuk meg a legfelső szintű kódban. A megírt metódus írása során hivatkozzuk be a `System.Net.Http` névteret. A kód semmi mást nem csinál, csak elindít aszinkron módon egy HTTP GET kérést a megadott URL-re, illetve a válasz tartalmát is aszinkron módon kiolvassa és kiírja a konzolra.
80
+
Vegyünk fel egy új metódust és hívjuk meg a legfelső szintű kódban. A megírt metódus írása során hivatkozzuk be a `System.Net.Http` névteret. A kód semmi mást nem csinál, csak elindít aszinkron módon egy HTTP GET kérést a megadott URL-re, illetve a válasz tartalmát is aszinkron módon kiolvassa és egy részét kiírja a konzolra.
*await:* Mindig egy `Task` `await`-elhető (vagy taszk szerű dolog: vagyis van neki `GetAwaiter` metódusa, ami meghatározott metódusokkal rendelkező objektummal tér vissza)! Akár létre is hozhatunk egy `Task`-ot, amit egy lokális változóban tárolunk, akkor azt is tudjuk `await`-elni.
102
102
103
-
*async:* ha await-elni akarunk, akkor muszáj `async`-nak lennie a tartalmazó metódusnak, mert ilyenkor építi fel a fordító az aszinkron végrehajtáshoz szükséges állapotgépet.
103
+
*async:* Ha await-elni akarunk, akkor muszáj `async`-nak lennie a tartalmazó metódusnak, mert ilyenkor építi fel a fordító az aszinkron végrehajtáshoz szükséges állapotgépet.
104
104
105
-
Debuggoljuk ki! Minden `Console`, `async` sorra tegyünk töréspontot, debuggolás során (kbd:[F5]) kövessük végig milyen sorrendben éri el őket a végrehajtás. Nézzük meg melyik rész milyen szálon fut le (debug közben menu:Debug[Windows > Threads]). A `LoadWebPageAsync` utáni rész előbb fog lefutni, mint az első `await` utáni rész. Az `await` utáni rész nem a _Main Thread_-en fut. Figyeljük meg azt is, hogy az _Ez a vége_ szöveg hamarabb kiíródik, mit a HTML oldal letöltése.
105
+
Debuggoljuk ki! Minden `Console`, `async` sorra tegyünk töréspontot, debuggolás során (kbd:[F5]) kövessük végig, milyen sorrendben éri el őket a végrehajtás. Nézzük meg, melyik rész milyen szálon fut le (debug közben menu:Debug[Windows > Threads]). A `LoadWebPageAsync` utáni rész előbb fog lefutni, mint az első `await` utáni rész. Az `await` utáni rész nem a _Main Thread_-en fut. Figyeljük meg azt is, hogy az _Ez a vége_ szöveg hamarabb kiíródik, mint a HTML oldal letöltése.
106
106
107
107
Próbáljuk ki a `Console.ReadKey`-t kikommentezve is, ilyenkor jó eséllyel hamarabb leáll a process, minthogy a `Task` befejeződne. Az ilyen fire-and-forget típusú hívásoknál nem figyel arra senki, hogy itt még valami háttérművelet folyik.
108
108
@@ -119,7 +119,7 @@ Módosítsuk a `LoadWebPageAsync` fejlécét, hogy taszkot adjon vissza:
119
119
public static async Task LoadWebPageAsync() //void helyett Task
120
120
----
121
121
122
-
Várjuk be az szinkron művelet végét a legfelső szintű kódban.
122
+
Várjuk be az aszinkron művelet végét a legfelső szintű kódban.
123
123
124
124
[source,csharp]
125
125
----
@@ -191,7 +191,7 @@ class Person
191
191
}
192
192
----
193
193
194
-
Ez máris számos figyelmeztetést generál. A nem nullozható referencia típusok bekapcsolásával alapesetben nem hibák csak új figyelmeztetések generálódnak. A vezetéknév és keresztnév adatoknak nem szabadna `null` értékűnek lennie (a sima `string` típus nem nullozható típust jelent), viszont így az alapérték nem egyértelmű, explicit inicializálnunk kellene.
194
+
Ez máris számos figyelmeztetést generál. A nem nullozható referencia típusok bekapcsolásával alapesetben nem hibák, csak új figyelmeztetések generálódnak. A vezetéknév és keresztnév adatoknak nem szabadna `null` értékűnek lennie (a sima `string` típus nem nullozható típust jelent), viszont így az alapérték nem egyértelmű, explicit inicializálnunk kellene.
195
195
196
196
Fontos megértenünk, hogy a string típus fizikailag továbbra is lehet null értékű, mindössze a fordító számára jelezzük, hogy szándékunk szerint sohasem szabadna `null` értéket felvennie. A fordító cserébe figyelmeztet, ha ezt megsértő kódot detektál.
197
197
@@ -318,7 +318,7 @@ Mivel ez csak egy példakód, ne javítsuk ki a hibákat, csak távolítsuk el a
318
318
319
319
=== Tuple nyelvi szinten, lokális függvények
320
320
321
-
Készítsünk Fibonacci számsor kiszámolására alkalmas függvényt, ahol használjunk ki az alábbi két új nyelvi elemet. Természetesen nagyon sokféleképpen meg lehetne valósítani ezt a metódust, de most kifejezetten a _tuple_-ök nyelvi támogatását és lokális függvényeket szeretnénk demonstrálni.
321
+
Készítsünk Fibonacci számsor kiszámolására alkalmas függvényt, ahol használjuk ki az alábbi két új nyelvi elemet. Természetesen nagyon sokféleképpen meg lehetne valósítani ezt a metódust, de most kifejezetten a _tuple_-ök nyelvi támogatását és lokális függvényeket szeretnénk demonstrálni.
322
322
323
323
* Lokális függvények: ezek a függvények csak adott metódusban láthatók. Két esetben érdemes őket használni: ha nem szeretnénk „szennyezni” a környező osztályt különféle privát segédmetódusokkal, vagy ha egy mélyebb, komplexebb hívási láncban nem szeretnénk a paramétereket folyamatosan továbbpasszolni, ugyanis ezek a metódusok elérik a külső scope-on található változókat is (a lenti esetben például az `x`-et).
324
324
@@ -392,7 +392,7 @@ Ha kérjük a villanykörte segítségét az `IDisposable`-ön, akkor 2x2 lehet
392
392
393
393
image::images/csharp4-dispose.png[Dispose minta implementálása IntelliSense segítségével]
394
394
395
-
Fussuk át a generált kódot, ami szépen kommentezett. A pattern lényege, hogy a nem menedzselt erőforrásokat (_unmanaged objects / resources_) szükséges felszabadítanunk, amit a `Dispose` metódusokban, illetve menedzselt kód esetén a kommentekkel kijelölt helyen érdemes ezt elvégeznünk. Készítsük el az időmérő mechanizmust!
395
+
Fussuk át a generált kódot, ami szépen kommentezett. A pattern lényege, hogy a nem menedzselt erőforrásokat (_unmanaged objects / resources_) szükséges felszabadítanunk, amit a `Dispose` metódusokban, illetve menedzselt kód esetén a kommentekkel kijelölt helyen érdemes elvégeznünk. Készítsük el az időmérő mechanizmust!
396
396
397
397
[source,csharp]
398
398
----
@@ -445,7 +445,7 @@ Hívjuk meg a `foreach` ciklusból:
0 commit comments