Úvod Přetěžování Generika Kolekce Konec
Programování v C# Další jazykové konstrukce
Petr Vaněček
1 / 31
Úvod Přetěžování Generika Kolekce Konec
Obsah přednášky
I
Přetěžování I I
I I
metody operátory
Generika Kolekce I I
třídy rozhraní
2 / 31
Úvod Přetěžování Generika Kolekce Konec
Překrytí vs. přetížení
I
Rozdíl ve způsobu deklarace metody/operátoru I I
deklarace: název a seřazený seznamu parametrů překrytí (override) I I
I
stejný název, stejné parametry např. A.Tiskni(int i) a B.Tiskni(int i)
přetížení (overload) I I
stejný název, různé parametry např. A.Tiskni(int i) a B.Tiskni(float f)
3 / 31
Úvod Přetěžování Generika Kolekce Konec
Překrytí vs. přetížení
I
Překrytí I I I
Shodná deklarace; nemůže být v jedné třídě Odděděné třídy mohou dodat vlastní funkčnost k metodě Pokud je metoda virtuální I I I
I
Pokud není metoda virtuální I I
I
mechanismus polymorfismu použije se dynamicky určený typ např. A b = new B(); b.M(); volá B.M() použije se statický typ např. A b = new B(); b.M(); volá A.M()
Přetížení I
Deklarace liší; může (nemusí) být ve stejné třídě
4 / 31
Úvod Přetěžování Generika Kolekce Konec
Přetížení I
Přetížené metody by měly poskytovat podobnou funkčnost I
vhodné používat v případě že metoda s méně parametry volá metodu s více parametry I I
I
usnadňuje údržbu – hlavní kód je jen na jednom místě usnadňuje práci – pokud nepotřebujeme nějakou specialitku, stačí nám volat jednodušší metodu
např. Open ( string name , FileMode mode ) { ... } Open ( string name , FileMode mode , FileAccess access ) { ... }
I
pro jednoduchou práci nepotřebuju znát nic o typech přístupu
5 / 31
Úvod Přetěžování Generika Kolekce Konec
Přetížení I
Názvy parametrů by měly být samopopisné I I I
nepoužívat názvy parametrů jako s, i, cislo, . . . názvy u složitějších metod by navíc měly vypovídat o výchozí hodnotě např. int Compare ( string str1 , string str2 ) { Compare ( str1 , str2 , false ); } int Compare ( string str1 , string str2 , bool ignoreCase ) { ... }
I
parametr ignoreCase naznačuje, že není-li uveden bude záležet na velikosti písma
6 / 31
Úvod Přetěžování Generika Kolekce Konec
Přetížení
I
Pořadí a názvy parametrů u přetížených metod by se neměly měnit I
I
Jako virtuální by měla být označena pouze kompletní metoda I I
I
usnadňuje volání rozšířených metod pouhým přidáním dalšího parametru metody s nižším počtem parametrů ji volají většinou není důvod aby byly měněny
U referenčních typů by se měla uvažovat i hodnota null I I
stejné jako neudaný parametr otestuje se pouze na jednom místě a ne při každém volání
7 / 31
Úvod Přetěžování Generika Kolekce Konec
Operátory
I
Jiný způsob zápisu funkce I
I I
a + b → Secti(a,b)
Zpřehledňují zápis a zvyšují čitelnost kódu Používat s rozumem I I I
u datových typů u kterých operace dávají smysl v případech kdy je na první pohled zřejmé co má operátor dělat přetěžovat operátory symetricky I
když je operátor <, nadefinovat i >
8 / 31
Úvod Přetěžování Generika Kolekce Konec
Přetížitelné operátory I
Typy přetížitelných operátorů I
unární I
binární
I
porovnání
I
I I
I
+, -, !, ∼, ++, --, true, false
I
+, -, *, /, %, &, |, b, <<, >> ==, !=, <, >, <=, >=
konverzní operátory
Částečně přetížitelné operátory I
přiřazovací I I
I
+=, -=, *=, /=, ... přetížené automaticky, pokud existuje odpovídající binární operátor
podmínkové I I
&&, || lze obejít přetížením operátorů true a false 9 / 31
Úvod Přetěžování Generika Kolekce Konec
Vytvoření přetížení operátorů
I
Operátory musí být public static
I
Třída/struktura implementující operátor musí být alespoň jedním z operandů Unární operátory
I
I
I
I
I
public static
operator +( op1, op2)
Explicitní typová konverze I
I
public static operator +( op)
Binární operátory
public static explicit operator ( op)
Implicitní typová konverze I
public static implicit operator ( op)
10 / 31
Úvod Přetěžování Generika Kolekce Konec
Příklady struct Complex { public double im ; public double re ; public static Complex operator -( Complex op ) { Complex res ; res . re = - op . re ; res . im = - op . im ; return res ; } public static Complex operator +( Complex op1 , Complex op2 ) { Complex res ; res . re = op1 . re + op2 . re ; res . im = op1 . im + op2 . im ; return res ; } public static implicit operator double ( Complex op1 ) { return op1 . re ; } } 11 / 31
Úvod Přetěžování Generika Kolekce Konec
Obecné třídy I
Při psaní kódu jsou často potřebné datové struktury pro různé datové typy I I I I
I
seznamy zásobníky fronty ...
Možné řešení – využít OOP I I
navrhnout třídu pro rodičovský typ (např. System.Object při přístupu využívat plymofrismus
public class Zasobnik { object [] polozka ; public void Vloz ( object polozka ) {...} public object Vyber () {...} } 12 / 31
Úvod Přetěžování Generika Kolekce Konec
Nevýhody objektového řešení
I
Nízký výkon I
u hodnotových typů musí dojít k boxing a unboxing I I
I
I
volání metody zaměstnání GC
ani při použití referenčních typů není vyhráno
Typová (ne)bezpečnost I
explicitní přetypování
Zasobnik z = new Zasobnik (); z . Vloz (3.3); int i = ( int ) z . Vyber (); // výjimka
13 / 31
Úvod Přetěžování Generika Kolekce Konec
Specializované typy
I
Možné řešení problémů I
vytvořit pro každý potřebný datový typ specializovanou třídu class IntZasobnik { int [] polozka ; ... }
I
Nový problém I I
stejný (podobný) kód na více místech v případě chyby nákladná oprava
14 / 31
Úvod Přetěžování Generika Kolekce Konec
Co jsou generika
I
Umožňují nadefinovat obecné třídy I
typová bezpečnost I I
nedochází k přetypovávání, pracuje se přímo s požadovaným typem možno omezit typy, které mohou být použity
I
snadná znovu využitelnost kódu
I
výkonost
I
I I
stačí vytvořit instanci s požadovaným typem typová kontrola je provedena při překladu neprovádí se (un)boxing
15 / 31
Úvod Přetěžování Generika Kolekce Konec
Generika v .NET
I I
Nově ve verzi 2.0 Součást CLI specifikace I
I
možno používat v ostatních .NET jazycích
Přímá podpora v IL I
generická třída se přeloží jako normální třída I
I
vyznačená místa pro nahrazení konkrétními typy
k vytvoření konkrétní instance dochází až za běhu
16 / 31
Úvod Přetěžování Generika Kolekce Konec
Použití generik I I
Lze použít pro třídy, struktury, rozhraní, metody a delegáty Příklad public class Zasobnik { T [] polozka ; public void Vloz ( T polozka ) {...} public T Vyber () {...} } ... Zasobnik < int > z = new Zasobnik < int >(); z . Vloz (3); int i = z . Vyber ();
I I
Generický typ se uvádí v < > Název typu může být libovolný identifikátor I
I
používá se jednopísmenný, velké písmeno
Při použití se musí uvádět konkrétní typ 17 / 31
Úvod Přetěžování Generika Kolekce Konec
Použití více typů
I
Při deklaraci lze použít i více generických typů
I
Příklad public Uzel { K klic ; H hodnota ; Uzel dalsi ; } ... Uzel < int , string > uzel = new Uzel < int , string >();
18 / 31
Úvod Přetěžování Generika Kolekce Konec
Omezení I
Problém při použití generických typů I I
obecně můžeme za generický typ dosadit libovolný konkrétní typ nelze volat konkrétní funkce I I
I
Možnost vymezit, které typy mohou být použity I
pomocí slova where I I I I I
I
např. test na rovnost či porovnání nejsou součástí System.Object
třídy rozhraní new() – musí mít neparametrický konstruktor struct – musí být hodnotový typ class – musí být referenční typ
Příklad class PoleHodnot where T : struct { ... } 19 / 31
Úvod Přetěžování Generika Kolekce Konec
Kolekce
I
Umožňují sdružovat položky stejného typu do skupin I I I I
I
seznamy slovníky fronty ...
S příchodem .NET 2.0 I
zavedení generických kolekcí I I
I
větší efektivita vyšší typová bezpečnost
vytvoření některých nový kolekcí
20 / 31
Úvod Přetěžování Generika Kolekce Konec
List (ArrayList) I I
Pole s dynamicky se zvětšující délkou Konstruktor I I
I
Vlastnosti I I I
I
možno nastavit počáteční délku vytvořit z pole (ICollection) Count – počet položek Capacity – velikost pole Item – indexový přístup k položkám
Metody I I I I I I
Add(item) – přidá prvek na konec seznamu Remove(item) – vyjme prvek RemoveAt(index) – vyjme prvek na pozici Sort() – setřídí pole BinarySearch() – najde metodou půlení intervalu ToArray – převede na pole 21 / 31
Úvod Přetěžování Generika Kolekce Konec
Další seznamy
I
LinkedList I
Dvojitě zřetězený seznam I
I
I
skládá se z uzlů LinkedListNode
Rychlé operace vkládání a vyjmutí pomocí AddAfter/Before/First/Last, RemoveFirst/Last
SortedList I
Pole s binárním stromem I I
I I
ukládá se dvojice klíč/hodnota možnost indexovaného přístupu
Vlastnosti Item, Keys, Values Metody Add, Remove, RemoveAt
22 / 31
Úvod Přetěžování Generika Kolekce Konec
SortedDictionary
I
Podobný jako SortedList I I
I
Používá pouze stromovou strukturu I I
I
neumožňuje indexovaný přístup operace vkládání a vybírání O(logn)
Vlastnosti I I
I
dvojice klíč/hodnota vyhledávání pomocí stromu
Item[klíč] – vrátí položku podle klíče Keys/Values – kolekce klíčů/hodnot
Metody I I
Add/Remove – přidá/ubere položku ContainsKey/Value – dotaz zda obsahuje klíč/hodnotu
23 / 31
Úvod Přetěžování Generika Kolekce Konec
Dictionary (HashTable)
I
Hash tabulka I I
I
dvojice klíč/hodnota rychlé operace (O(1))
Vlastnosti a metody I
podobné jako SortedDictionary
24 / 31
Úvod Přetěžování Generika Kolekce Konec
Porovnání
metoda List LinkedList SortedList SortedDictionary Dictionary
vkládání O(n) O(1) O(n) O(log n) O(1)
vyjmutí O(n) O(1) O(n) O(logn) O(1)
hledání O(n) O(n) O(logn) O(logn) O(1)
reprezentace pole spojový seznam pole+strom red-black strom hash tabulka
25 / 31
Úvod Přetěžování Generika Kolekce Konec
Fronty a zásobníky
I
Queue I I
Reprezentuje frontu Vlastnosti I
I
I I I
I
Count – počet prvků ve frontě
Metody Enqueue – přidá prvek na konec fronty Dequeue – odebere prvek ze začátku fronty Peak – vrátí první prvek (bez odebrání)
Stack I I
Reprezentuje zádobník Metody I I
Push – vloží prvek na vrchol Pop – odebere prvek z vrholu
26 / 31
Úvod Přetěžování Generika Kolekce Konec
Rozhraní Collections
I
Umožňují vytvářet vlastní kolekce I I
I
snadná záměna jednoho typu za jiný používání ve foreach cyklech
ICollection I I
obecná kolekce vlastnosti I I
I
Count – počet prvků v kolekci IsReadOnly
metody I I I I
Add – vložení prvku Remove – odtranění prvku Contains – zjištění zda prvek existuje Clear – vymazání kolekce
27 / 31
Úvod Přetěžování Generika Kolekce Konec
Specializovaná rozhraní I
IEnumerable I
umožňuje použít kolekci ve foreach cyklu metoda
I
příklad
I
I
GetEnumerator – vrací enumerátor, lze použít klíčové slovo yield
struct Vektor : IEnumerable < int > { public int x ,y , z ; public IEnumerator < int > GetEnumerator () { yield return x ; yield return y ; yield return z ; } IEnumerator IEnumerable . GetEnumerator () { return GetEnumerator (); } } 28 / 31
Úvod Přetěžování Generika Kolekce Konec
Specializovaná rozhraní
I
IList I I I
potomek ICollection kolekce objektů přístupných pomocí indexů vlastnosti I I
I
Item – indexer, vrátí/nastaví prvek s indexem int i IsFixedSize – kolekce s omezenou velikostí
metody I I I
IndexOf – vrátí index hledaného prvku (-1 v případě neexistence) Insert – vloží prvek na pozici int i RemoveAt – odebere prvek z pozice int i
29 / 31
Úvod Přetěžování Generika Kolekce Konec
Specializovaná rozhraní
I
IDictionary I I I
potomek ICollection kolekce klíčů a hodnot vlastnosti I I I
I
Item – indexer, vrátí/nastaví prvek s klíčem key Keys – kolekce klíčů Values – kolekce hodnot
metody I I I I
Add – přidá dvojici klíč/hodnota ContainsKey – zjistí zda klíč existuje Remove – odebere prvek s klíčem key TryGetValue – spojení ContainsKey a Item
30 / 31
Úvod Přetěžování Generika Kolekce Konec
Konec
31 / 31