C# nyelvi eszközök hatékony használata Flashcards

1
Q

Nyelvi elemek

A
  1. Implicit változó típus (var) használata
  2. Readonly a const helyett
  3. Cast helyett is/as
  4. String.format() helyett interpolált string
  5. Kultúra-specifikus esetben FormattableString használata
  6. Stringesen leírt API-k kerülése
  7. Visszahívások kifejezése Delegate-el
  8. Null conditional (? operátor) használata Event Invocation esetén
  9. Boxing és Unboxing minimalizálása
  10. new modifier használata szülő osztály nonvirtual metódusaira
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Implicit változó típus (var) használata

A

Ez nem egy dinamikus típus, hanem a jobb oldal által meghatározott típus.
Ne minden esetben ezt használjuk, mert veszít kódunk az olvashatóságából, a szám típusok veszítenek pontosságukból.
Használjuk akkor, ha nem vagyunk biztosak egy adott változó típusában (pl lokális változó, ami egy db query eredménye).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Readonly a const helyett

A

Readonly-t kell preferálni, mert a const csak szám, string és null lehet. Readonly ezzel szemben bármi, használható vele a new kulcsszó is.
Const fordítási időben rögzül, readonly futásidőben helyben vagy konstruktoron keresztül

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Cast helyett is/as

A

Castolás esetén null check és kivétel kezelés is szükséges, míg is/as esetében a visszatérési értéket kell null checkelni. Az is/as operátorok ellenőrzik a futásidő közbeni objektum típusát és nem végeznek rajta műveletet, kivéve a boxing, ha az szükséges.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

String.format() helyett interpolált string

A

Olvashatóbb kódot eredményez, a compiler számára is jobb static type check szempontból. String.Format() esetén a compiler nem validálja az argumentumok számát, nehézzé válik azok ellenőrzése. Interpolált string esetén van validáció erre, bármilyen C# expression elhelyezhető benne elágazást és ciklust leszámítva

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Kultúra-specifikus esetben FormattableString használata

A

Egy interpolált stringből készíthetünk FormattableString típust, amit utána szabadabban újra felhasználhatunk más kultúrákban is megszokott módon egyszerűen.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Stringesen leírt API-k elkerülése

A

A nameof() operátor előnyben részesítése, mert így az adott változó átnevezését követően minden nameof() ban megjelenésénél is dinamikusan megtörténik az átnevezés

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Visszahívások kifejezése Delegate-el

A

A Delegate egy olyan objektum, ami metódus refeneciát tartalmaz, ezért típushoz nem kötött, futásidőben configurálható több vevő értesítésére. Pár beépített példa: .Range(), .Find(), .TrueForAll(), .ForEach() stb.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Null Conditional (? Operátor) használata Event Invocation esetén

A

A null-check legegyszerűbb módja event invocation esetén a ? operátor: kompakt és könnyen olvasható, a complier type-safe Invoke() metódust generál minden delegate-re az event definíciójában. Mindezek mellett ez az operátor szál biztos!

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Boxing és Unboxing minimalizálása

A

Kerüljük a system.object típusba más típusú változók pakolását és az erre a típusra való implicit konvertálást. Ez a típus a heap-en jön létre, ekkor egy érték típus konvertálódik referencia típussá

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

new modifier használata szülő osztály nonvirtual metódusaira

A

A nonvirtual metódusok statikusan kötődnek, a virtuálisak dinamikusan.
Nem kell minden metódust virtuallá tenni a szülő osztályban, csak amiket a leszármazott osztályoknak meg kell változtatnia. A new modifiert akkor használjuk, ha egy szülő osztálybeli metódus új verzióját akarjuk létrehozni ugyanazon a néven
egy leszármazott osztályban!

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

General programming

A
  1. Minimális ÉS elégséges megszorítások definiálása
  2. Generikus algoritmusok specifikálása futásidei típus ellenőrzéssel
  3. Reláció definiálása beépített interfacekkel
  4. Generikus osztályok IDisposable megvalósítása
  5. Generikus covariance és contravariance támogatása
  6. Delegate-k használata metódus megszorításként a típus paramétereken
  7. Ne specifikáljunk generikus szülő osztályban és interfaceben
  8. Generikus metódusok használata
  9. Klasszikus interfacek implementálása a generikus mellett
  10. Minimális interface contract a kiterjesztő metódusokkal
  11. Típus specifikus gyűjteményekhez generikus segéd metódusok
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Minimális ÉS elégséges megszorítások definiálása

A

A megszorítások azt kommunikálják a compiler felé, hogy a T-től funkcionalitásokat várunk el a system.object funkcionalitásokon felül. Jól definiált megszorítások kevesebb kódot, kevesebb runtime errort és egyéb hibát eredményeznek.
Sok kódot megspórolhatunk, ha egy metódusban nem manuálisan validáljuk a bemenő T paramétereket, hanem pl interface contract-tal tesszük ezt.
~~~
public static bool AreEqual2<T>(T left, T right)
where T : IComparable<T> =>
left.CompareTo(right) == 0;</T></T>

~~~

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Generikus algoritmusok specifikálása futásidei típus ellenőrzéssel

A

Futásidőben nem tudjuk még mi lesz T ezért készüljünk fel minden olyan típusra amit máshogy szeretnénk kezelni.
Példa:
~~~
public class GenericAlgorithm<T>
{
public void ProcessData(T data)
{
// Futásidei típusellenőrzés
if (data is int)
{
int intValue = (int)data;
Console.WriteLine($"Process int data: {intValue}");
}
else if (data is string)
{
string stringValue = (string)data;
Console.WriteLine($"Process string data: {stringValue}");
}
else
{
Console.WriteLine("Unsupported data type");
}
}
}</T>

~~~

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Reláció definiálása beépített interfacekkel

A

IComparable<T> és IComparer<T> használata, hogy különböző colection-ök az adott T-ből rendezhetőek legyenek.</T></T>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Generikus osztályok IDisposable megvalósítása

A

A megszorítások feladata runtime errorból compile-time errort csinálni, valamint dokumentációt adni az adott osztályt használóknak. Szükséges, hogy implementáljuk az IDisposable interfacet, így rendelkezhetünk a felszabadításról.

17
Q

Generikus covariance és contravariance támogatása

A

A covariance és contravariance megadja milyen körülmények között konvertálható egy típus egy másik típusra. Amikor lehetséges, tegyük ezeket lehetővé generikus interfacek és delegate-k esetén. Generikus T-nél használjuk az in/out kulcsszókat, hogy jelezzük a compilernek, ha esetleg csak be-, vagy kimeneti T lesz a T (pl out T esetén T nem módosul).

18
Q

Delegate-k használata metódus megszorításként a típus paramétereken

A

Ha az Osztályunknak akarunk Add() metódust, az IAdd<T> interface megalkotásával kezdjük úgy, hogy az támogassa a Delegate alapú interface contractokat.</T>

19
Q

Ne specifikáljunk generikus szülő osztályban és interfaceben

A

Ha generikus osztályt/interfacet írunk, a metódusok benne legyenek generikusok, ne típus specifikusak.

20
Q

Generikus metódusok használata

A

Generikus metódusokat használhatuk nem generikus osztályokban is, de célravezető, ha generikus osztályokban tesszük, így egyszerűbb a kód.

21
Q

Klasszikus interfacek implementálása a generikus mellett

A

Ha több hasonló típus van, generikusan nehéz jó megoldást adni pl egyenlőség vizsgálatukra. Ilyenkor specializálni kell az egyik típusra, az IEquatable<t>-t implementálni, majd az overrideon belül az is/as kulcsszókkal specializálni.</t>

22
Q

Minimális interface contract a kiterjesztő metódusokkal

A

Generikus metódus szinten használhatuk interface contractot (where T: valami).

23
Q

Típus specifikus gyűjteményekhez generikus segéd metódusok

A

Ha típus specifikus gyűjteményeket használunk, írhatunk hozzájuk generikus Min(), Max(), Sum(), Avg(), stb metódusokat.

24
Q

Kivételkezelés

A
  1. Kivételek használata metódus contract hiba jelzésére
  2. Using/try-finally használata erőforrás felszabadításra
  3. Készítsünk saját exception osztályokat saját use-casekre
  4. Garantáljuk a program futását exception esetén:
  5. Exception filter használata catch és re-throw helyett
  6. Mellékhatások kezelése exception filterrel
25
Q

Kivételek használata metódus contract hiba jelzésére

A

Egy metódusnál előre beláthatatlan hibák keletkezhetnek melyek megszakíthatják a program normál működését ezért hozzunk létre több publikus metódust melyek nevei arra utalnak, hogy lehetséges, hogy kivétel fog keletkezni, ezzel minimalizálva annak az esélyét hogy a metódust használó személy nem várt hibát fog futásidőben kapni. A TryDoWork() metódus validálja a bemeneti paramétereket és a metódus futásához szükséges belső paramétereket, majd meghívja a Work() metódust, rossz paraméterek esetén nem dob kivételt. A DoWork() metódus meghívja a Work() metódust, de hibát dobunk benne ha valami nem megfelelő. (A Work() metódus privát)
Röviden olyan ha egy olyan metódust írunk amiben keletkezhet kivétel szolgáltassunk olyan metudóst is mellé amely validál, de nem keletkezik kivétel sikertelenség esetén.

26
Q

Using/try-finally használata erőforrás felszabadításra

A

Használjuk az IDisposable interface Dispose() metódusát using vagy try-finally blokkban, ha a használt típus ezt implementálja. A Dispose() nem távolít el objektumokat a memóriából, ez csak egy hook, ami lehetővé teszi a kezeletlen erőforrások felszabadítását.

27
Q

Készítsünk saját exception osztályokat saját use-casekre

A

Mivel az a good practice, ha minden lehetséges hibára más catch ágat írunk, így előnyös, ha saját típusainkhoz saját kivétel típusokat is definiálunk. Ezekben érdemes az eredeti hibát is eltárolni, mint inner exception, majd több kontextust hozzáadni a hiba természetéről.

28
Q

Garantáljuk a program futását exception esetén

A

Strong Guarantee preferálása annyit tesz, hogy egy művelet vagy lefut helyesen, vagy nem változtat a program állapotán. Utóbbi esetben a keletkező hibát úgy kell lekezeni, hogy annak ne maradjon nyoma a futás további részében.

29
Q

Exception filter használata catch és re-throw helyett

A

Az exception filter egy when(feltétel), ami a catch-hez csatlakozik. Ennek segítségével a több információ áll rendelkezésre debugging közben, valamint jobb lesz a program teljesítménye is.
~~~
try{}
catch (Exception ex) when (ex is MyCriticalException)
{
// Handle critical error
}
catch (Exception ex){ // Handle other exceptions }
~~~

30
Q

Mellékhatások kezelése exception filterrel

A

Oximoronnak tűnik, de használhatunk olyan filtert, ami mindig hamis, vagy épp mindig igaz. Ennek egyértelmű célja például a hiba logolás valahogy így:
~~~
catch(Exception e) when log(e) {}
~~~
Ezt bármely try-catch blokkba beilleszthetjük első catch ágnak, a futást nem fogja befolyásolni, cserébe információt gyűjt a hibákról.