C# nyelvi eszközök hatékony használata Flashcards
Nyelvi elemek
- Implicit változó típus (var) használata
- Readonly a const helyett
- Cast helyett is/as
- String.format() helyett interpolált string
- Kultúra-specifikus esetben FormattableString használata
- Stringesen leírt API-k kerülése
- Visszahívások kifejezése Delegate-el
- Null conditional (? operátor) használata Event Invocation esetén
- Boxing és Unboxing minimalizálása
- new modifier használata szülő osztály nonvirtual metódusaira
Implicit változó típus (var) használata
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).
Readonly a const helyett
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
Cast helyett is/as
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.
String.format() helyett interpolált string
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
Kultúra-specifikus esetben FormattableString használata
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.
Stringesen leírt API-k elkerülése
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
Visszahívások kifejezése Delegate-el
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.
Null Conditional (? Operátor) használata Event Invocation esetén
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!
Boxing és Unboxing minimalizálása
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á
new modifier használata szülő osztály nonvirtual metódusaira
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!
General programming
- Minimális ÉS elégséges megszorítások definiálása
- Generikus algoritmusok specifikálása futásidei típus ellenőrzéssel
- Reláció definiálása beépített interfacekkel
- Generikus osztályok IDisposable megvalósítása
- Generikus covariance és contravariance támogatása
- Delegate-k használata metódus megszorításként a típus paramétereken
- Ne specifikáljunk generikus szülő osztályban és interfaceben
- Generikus metódusok használata
- Klasszikus interfacek implementálása a generikus mellett
- Minimális interface contract a kiterjesztő metódusokkal
- Típus specifikus gyűjteményekhez generikus segéd metódusok
Minimális ÉS elégséges megszorítások definiálása
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>
~~~
Generikus algoritmusok specifikálása futásidei típus ellenőrzéssel
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>
~~~
Reláció definiálása beépített interfacekkel
IComparable<T> és IComparer<T> használata, hogy különböző colection-ök az adott T-ből rendezhetőek legyenek.</T></T>