this dir | view | cards | source | edit | dark top

Programování v C#

Programování v C#

principy Pythonu

v C/C++

C#

Typy

základní dělení všech typů

Typy

overhead u každého objektu na haldě (má typicky 16 B)

Typy

dotnetový typ System.Int16 → C# klíčové slovo short

pokud klíčové slovo existuje, používáme ho

Typy

třídy a struktury můžeme anotovat slovem record

Typy

properties – gettery, settery

Typy

primary constructors – v C# 12, fieldy píšu do závorky za class C

Typy

nullable hodnotové typy – pomocí otazníku, vytvoří se generická struktura Nullable, je tam boolean vlastnost HasValue

lze přetěžovat porovnání, takže někdy může být problém porovnávat s nullem → může se hodit použít operátor is nebo is not

Typy

null původně vychází z referenčních typů

Typy

nová sémantika referenčních typů od C# 8

Kontrakt a rozhraní (interfaces)

koncepční rozdíl mezi C# a Pythonem

Překlad a distribuce programů

C++

Překlad a distribuce programů

Apple

Překlad a distribuce programů

C#

Dědičnost

dědičnost/inheritance

Konstanty, konstruktory, výčty

konstanty uvnitř tříd

Konstanty, konstruktory, výčty

class constructor

Konstanty, konstruktory, výčty

i když to vypadá, že se volá víc konstruktorů u dané třídy (typicky pomocí : this(…)), tak na úrovni CIL kódu tu instanci inicializuje jenom jeden z těch konstruktorů – ten, který se volá jako první (tedy ten this(…))

Konstanty, konstruktory, výčty

dalším výrazem, jehož hodnota se generuje za překladu, je nameof(proměnná)

Konstanty, konstruktory, výčty

když píšu číslo a chci ho zpřehlednit, tak můžu použít podtržítko

např. int speed = 300_000;

Konstanty, konstruktory, výčty

výčtové typy (enum)

Konstanty, konstruktory, výčty

klíčové slovo using umožňuje nastavit alias pro název typu (např. using X = Console;), funguje i global using

má to smysl jen ve výjimečných situacích (pokud má něco krkolomný název)

Konstanty, konstruktory, výčty

situace: chceme mít uložený řádek a sloupec tabulky a chceme předejít tomu, abychom ta dvě čísla zaměnili

Měření rychlosti

měření rychlostí sčítání

Měření rychlosti

pokud funkci volám opakovaně (v cyklu), většinu času zabere běh prologu a epilogu – řešením by bylo to tělo funkce zkopírovat přímo do cyklu, což by ale bylo v rozporu s guidelines

Virtuální metody

už umíme zakrýt metodu rodiče pomocí klíčového slova new

synovská třída pak má dvě metody s daným názvem – jednu svoji a jednu od rodiče

Virtuální metody

virtuální metoda A.f()

Virtuální metody

u zakrytí metody se používá klíčové slovo new – bez něj nám překladač vyhodí warning

Virtuální metody

abstraktní metoda (klíčové slovo abstract) – je to virtuální metoda bez implementace

nesmíme vyrábět instance třídy s abstraktní metodou, takže třída musí být abstraktní

Virtuální metody

JIT: call vs. callvirt

Virtuální metody

Java

Virtuální metody

virtuální metody vs. interfaces

Virtuální metody

abstract method vs. interface

Virtuální metody

volání jiné implementace virtuální metody

Virtuální metody

ze stromu můžou padat i zlatá jablka

Virtuální metody

problém, když budeme mít jablečnou logiku v knihovně a.dll a jejich jezení v knihovně b.dll

Vlastnosti

ze setteru se vygeneruje metoda void set_X(int value)

value … kontextové klíčové slovo (je klíčovým slovem pouze v setteru vlastnosti)

Vlastnosti

syntaktická zkratka pro deklaraci jednoduché metody

Vlastnosti

vlastnost s getterem se dá zapsat různě

Vlastnosti

vlastnosti se obvykle pojmenovávají podstatnými jmény, metody slovesy (respektive začínají slovesem – třeba Get)

Vlastnosti

vlastnosti můžou být v interfacech

když v interfacu požaduju jen getter, můžu v jeho implementaci přidat i setter

Vlastnosti

u knihovny může dávat smysl rovnou použít vlastnost, než začít s fieldem a později ho předělat na vlastnost

změna fieldu na vlastnost mění rozhraní knihovny (a je potřeba opravit/překompilovat programy, které ji používají)

Vlastnosti

property Length u vektoru

Vlastnosti

vlastnosti můžou být i virtuální (nebo abstraktní)

Vlastnosti

pozor, pokud použiju syntaxi auto-implemented props s výchozí hodnotou, tak se ta hodnota jednou přiřadí do backing fieldu

pokud je výchozí hodnota nějaký field, tak pak pozdější změna hodnoty fieldu neovlivní hodnotu té vlastnosti

Vlastnosti

pozor na side-effects

Viditelnost

klíčová slova

Viditelnost

životnost lokální proměnných (scope)

Viditelnost

deklarace lokálních proměnných

Viditelnost

nelze přistupovat k neinicializované proměnné

Pointery a reference

co může být v proměnné

Pointery a reference

při takovém přiřazení se provádí boxing – je to implicitní alokace na GC haldě, alokuje se tam instance hodnotového typu (bude tam standardní overhead)

pozor: v Javě jsou dva různé typy, int (hodnotový) a Integer (referenční) – v C# je to ten samý typ System.Int32

Pointery a reference

co můžu dělat s proměnnou typu object?

můžu volat ToString()

Pointery a reference

co když máme long, zaboxujeme a chtěli bychom unboxovat do intu

Pointery a reference

pointery

Pointery a reference

někdy by se nám hodilo něco mezi referencemi a pointery

Pointery a reference

jazyk C++/CLI

Pointery a reference

bezpečný scénář – tracking reference má kratší životnost než věc, na kterou ukazuje

Pointery a reference

u referenčních typů obvykle nedává smysl používat tracking referenci

výjimečným případem, kdy to smysl dává, je třeba zvětšení pole – vyrobím nové pole, položky překopíruju a do tracking reference přiřadím nové pole

Pointery a reference

proto se u výstupních parametrů funkcí používá klíčové slovo out – na úrovni CIL kódu je to to samé, ale nevyžaduje to, aby proměnné byly inicializované

Pointery a reference

discard

Pointery a reference

středník

Pointery a reference

klíčové slovo in … proměnná uvnitř funkce funguje jako readonly (podobně celá struktura funguje jako readonly)

Interfaces a objekty podruhé

ale .ToString() se dá volat na každém objektu

v případě I i1 = new A();, kde I je interface, tedy funguje i1.ToString();

Interfaces a objekty podruhé

všechny hodnotové typy jsou implicitně sealed

Pole

fixní délka

Pole

na haldě je uložen overhead (syncblock + type), délka a jednotlivé hodnoty

v poli můžou být přímo hodnoty u hodnotových typů nebo adresy u referenčních typů

Pole

na prvek pole lze vytvořit tracking referenci

pozor, u objektů s indexerem tohle nefunguje

Pole

každé pole je potomkem typu Array

ale obvykle není dobrý nápad to používat

Pole

vícerozměrná pole

Pole

poznámka: default(T) vrací výchozí hodnotu pro typ T (dá se používat i zkráceně pomocí default)

po inicializaci pole jsou všechny hodnoty nastaveny na default

Pole

všechna pole mají runtimový range check

Pole

struktury v poli vs. v seznamu (List)

Pole

tracking reference se dá vrátit z metody – pokud ukazuje na něco jiného než na lokální proměnnou

Pole

ve strukturách nešlo inicializovat fieldy hodnotami kvůli implicitnímu volání bezparametrického konstruktoru nulujícího paměť

Pole

překladač kontroluje inicializaci jednotlivých fieldů struktury

takže není potřeba volat konstruktor

Goto

syntax

Goto

pravidla

Goto

rozumné použití

Goto

switch (jako void příkaz)

Goto

switch jako výraz

Goto

pattern matching

Výjimky

v objektu výjimky se obvykle ukládají data

Výjimky

informace o tom, o jakou výjimku se jedná, se dá uložit i v typu

je vhodné používat rozumnou hierarchii typů, aby uživatelé typů mohli výjimky filtrovat

Výjimky

mohlo by nás napadnout předalokovat objekt výjimky

Výjimky

catch blok má filtr na typ výjimky

pokud je bezparametrický, tak to je to samé, jako by tam byl typ Exception (v C# 1 to znamenalo něco jiného)

Výjimky

v catch bloku

Výjimky

poznámka k Nežárce

Výjimky

měli bychom používat vhodné typy výjimek

Výjimky

někdy upravujeme datovou strukturu

Výjimky

k čemu dalšímu se používá using

Výjimky

implementace IDisposable podle dokumentace (s destruktorem apod.) dává smysl pouze pokud mám pointer na externí unmanaged resource

Výjimky

když ve třídě používám disposable zdroje, tak může dávat smysl, aby třída byla tranzitivně také disposable a v dispose volat dispose na zdrojích

Výjimky

kde vznikají výjimky

Výjimky

zpracování výjimky v CLR

Výjimky

rozlišování výjimek

Výjimky

dodatek k výjimkám

Garbage collector

C-like

Garbage collector

C++ (volitelně)

Garbage collector

Rust (povinně)

Rc<T> (ref_count)

Garbage collector

odlišný přístup: garbage collection (GC)

Garbage collector

Large Object Heap (LOH)

když má objekt víc než 85 000 B

Garbage collector

adresový prostor

Garbage collector

reserve VA (parametr: počet bajtů) → kernel vrátí volnou adresu ve VA

Garbage collector

commit VA (adresa a počet bajtů) = alokace PA

Garbage collector

garbage collector vrací paměť operačnímu systému, když ji nepotřebuje

decommit = free

Garbage collector

módy: workstation × server

Garbage collector

garbage collector se pouští na základě alokace paměti

Windowsy vysílají broadcast zprávu, když dochází paměť počítači, takže i v této situaci se spouští garbage collection

Garbage collector

graf objektů

Garbage collector

proto se provádí heap compacting

Garbage collector

heaptop = vrchol haldy (kam se přidává nový objekt)

po heap compactingu se sníží

Garbage collector

udržuje se ukazatel na heaptop, při alokaci se jenom posune o velikost alokace

Garbage collector

short lived objekty

jsou fajn, protože žádný objekt nepřežije garbage collection, takže může proběhnout rychle a nemusí se dělat heap compacting

Garbage collector

generační GC

Garbage collector

memory leaky

Garbage collector

příklad: List<T>, implementujeme metodu Clear

Stringy

jsou immutable

Stringy

Appendy se dají řetězit

Stringy

string.Format (pomocí {0}, {1} apod.) vs. konkatenace

pozor na míchání přístupů – pokud uživatel zadá {0}, tak se to může rozbít

Stringy

interpolace pomocí $"xyz"

Hurá, máš hotovo! 🎉
Pokud ti moje kartičky pomohly, můžeš mi koupit pivo.