kst/icshp - 3. a 4. přednáška

127
Jazyk C# Přednáška 03/04 příkazy, operátory, OOP – třídy, vlastnosti, události

Upload: jan-hridel

Post on 13-Apr-2017

202 views

Category:

Education


0 download

TRANSCRIPT

Page 1: KST/ICSHP - 3. a 4. přednáška

Jazyk C# Přednáška 03/04 – příkazy, operátory, OOP – třídy, vlastnosti, události

Page 2: KST/ICSHP - 3. a 4. přednáška

Jan Hřídel [email protected]

• twitter: @h0nza

Page 3: KST/ICSHP - 3. a 4. přednáška

Myšlenka týdne

Page 4: KST/ICSHP - 3. a 4. přednáška

Zabalení (boxing) • Pokud je na místě, kde se očekává instance referenčního typu,

potřeba použít hodnotový typ (typicky předdefinované kolekce System.Collection), je potřeba zařídit převod.

• C# nabízí pro převod instance hodnotového typu na referenční typ operaci zabalení (boxing). Pro opačný převod pak vybalení (unboxing).

Page 5: KST/ICSHP - 3. a 4. přednáška

Zabalení (boxing) Pokud se přiřadí odkazu na typ object hodnota hodnotového typu, object o = 11;

vytvoří překladač instanci „obalové“ třídy, do které uloží hodnotu z pravé strany. Tuto hodnotu lze získat kdykoli zpět přetypováním int i = (int)o;

• Za běhu programu se kontroluje, zda má přetypování smysl. Jinak se vyvolává výjimka System.InvalidCastException

Page 6: KST/ICSHP - 3. a 4. přednáška

Příkazy • Hlavní rozdíly mezi C++ a C# V C# není příkaz asm.

Trochu odlišná pravidla platí pro switch a goto.

V C# má výrazový příkaz silnější pravidla.

V C# jsou příkazy navíc foreach, checked, unchecked, lock, using a yield.

Page 7: KST/ICSHP - 3. a 4. přednáška

Příkazy – základní konstrukce • Výrazový příkaz Vzniká připojením středníku na konec výrazu. Syntaxe

výraz ; Na rozdíl od C++ nelze použít libovolný výraz, ale pouze výraz, který má

vedlejší efekt.

A+B; 5;

Operátory ++, --, přiřazení, volání metody,

Page 8: KST/ICSHP - 3. a 4. přednáška

Příkazy – základní konstrukce • Blok Všude tam, kde lze použít příkaz, lze použít i složený příkaz – blok. Syntaxe

{ příkazynep } Libivolné příkazy včetně deklarací a

vnořených bloků.

Page 9: KST/ICSHP - 3. a 4. přednáška

Příkazy – základní konstrukce • Blok Na rozdíl od C++ nelze ve vnořeném bloku deklarovat stejný identifikátor

jako ve vnějším. { // Začátek vnějšího bloku int i = 5; { // Začátek vnitřního bloku int i = 6; } }

V C# chyba.

Page 10: KST/ICSHP - 3. a 4. přednáška

Příkazy – základní konstrukce • Deklarace Plnohodnotný příkaz – může se objevit kdekoli mezi ostatními příkazy.

Page 11: KST/ICSHP - 3. a 4. přednáška

Rozhodování • if Způsob použití je stejný jako v C++ Syntaxe

if (podmínka) příkaz1 if (podmínka) příkaz1 else příkaz2

podmínka – výraz typu bool nebo typu, který lze implicitně zkonvertovat na typ bool nebo na typ, který má operator true(). Na rozdíl od C++ zde nelze deklarovat proměnnou nebo použít čísla a reference.

Page 12: KST/ICSHP - 3. a 4. přednáška

Rozhodování • switch Syntaxe

switch (výraz) { alternativy }

alternativy: alternativa alternativa alternativy alternativa: návěští příkazy návěští: case konstanta : case konstanta : návěští default :

Page 13: KST/ICSHP - 3. a 4. přednáška

Rozhodování • switch Odlišnosti oproti C++

Jako konstanty v návěstích case lze použít i znakové řetězce a jako řídící výraz lze použít proměnnou typu string.

Program nesmí přejít automaticky z jedné alternativy do druhé – každá alternativa musí být ukončena break, goto, return nebo throw.

Program může přejít do jiné alternativy jen pomocí příkazu goto s uvedením návěstí.

Page 14: KST/ICSHP - 3. a 4. přednáška

Rozhodování • switch

Příklad: https://goo.gl/byJ9hf string s; while (true)

{

Console.WriteLine("Zadej text");

s = Console.ReadLine();

switch (s)

{

case "while":

case "switch":

Console.WriteLine("Zadal jsi klíčové slovo");

break;

case "konec":

return;

case "if":

goto case "while";

case "":

Page 15: KST/ICSHP - 3. a 4. přednáška

Cykly • V příkazu cyklu lze stejně jako v C++ používat příkazy break a continue.

• while Syntaxe

while(podmínka) příkaz

Odlišnosti oproti C++ jsou v podmínce – totéž jako u příkazu if

Page 16: KST/ICSHP - 3. a 4. přednáška

Cykly • for Syntaxe

for ( incializacenep ; podmínkanep ; kroknep ) příkaz

Zde lze deklarovat

proměnné. Lze uvést několik

výrazů oddělených

čárkou.

Platí totéž co pro podmínku příkazu if.

Jeden nebo skupina příkazů

oddělených čárkou.

Page 17: KST/ICSHP - 3. a 4. přednáška

Cykly • do-while Syntaxe

do příkaz while (podmínka)

Platí totéž co pro podmínku příkazu if.

Page 18: KST/ICSHP - 3. a 4. přednáška

Cykly • foreach Slouží k iteraci všech prvků v kolekci (kontejneru) Syntaxe

foreach(typ identifikátoru in výraz) příkaz

Musí určovat nějakou kolekci

Řídící proměnná cyklu. Deklarace

proměnné, do které se ukládají

jednotlivé hodnoty prvků z kolekce

Page 19: KST/ICSHP - 3. a 4. přednáška

Cykly • foreach Jako kolekci lze použít jakýkoli datový typ implementující rozhraní IEnumerable nebo jeho generickou obdobu, tedy typ obsahující veřejnou metodu GetEnumerator().

Jako kolekci lze též použít metodu či vlastnost obsahující iterátor.

Vrací hodnotu E, kterou lze použít jako enumerátor.

Page 20: KST/ICSHP - 3. a 4. přednáška

Cykly • foreach E implementuje Ienumerator, obsahuje tedy:

bool MoveNext()

Reset()

Current

Přejde na další prvek kolekce. Vrací false, pokud už další prvek v kolekci neexistuje.

Veřejná metoda. Nastaví enumerátor do výchozí pozice (před první prvek).

Vlastnost poskytující aktuální prvek kolekce.

Page 21: KST/ICSHP - 3. a 4. přednáška

Cykly • foreach Enumerátor může být jak referenčního, tak hodnotového typu. Průběh

• Vyhodnotí se výraz, tím se získá kolekce K. Má-li výraz hodnotu null, vyvolá se výjimka Syste.NullReferenceException.

• Pomocí K.GetEnumerator() se získá enumerátor E. Pokud je E referenčního typu a má hodnotu null, vyvolá se výjimka Syste.NullReferenceException

• Provádění cyklu skončí, když E.MoveNext() vrací false.

Page 22: KST/ICSHP - 3. a 4. přednáška

Skoky • jump statements – způsobují přenos řízení

• break, continue, goto, return a throw

Stejný jako v C++

Stejný jako v C++

Stejný jako v C++

Page 23: KST/ICSHP - 3. a 4. přednáška

Skoky • goto Syntaxe goto identifikátor ; goto default ; goto case konstanta ;

Stejný jako v C++

Pouze v těle příkazu switch.

Pouze v těle příkazu switch.

Page 24: KST/ICSHP - 3. a 4. přednáška

Skoky • Throw Význam stejný jako v C++ Slouží k vyvolání výjimky Syntaxe throw výraz ;

Odkaz na instanci třídy odvozené od System.Exception. Pokud je null, vyvolá

se System.NullReferenceException

Page 25: KST/ICSHP - 3. a 4. přednáška

Příkaz using • V C++ neexistuje

• Řídí životnost objektů, které zpravidla spravují resources (např. soubory)

• Syntaxe using (získání_prostředku) příkaz;

deklarace_lokální_proměnné výraz

Page 26: KST/ICSHP - 3. a 4. přednáška

Příkaz using • Prostředek – instance třídy nebo struktury, která

implementuje rozhraní System.IDisposable, které obsahuje metodu void Dispose().

• Deklarace lokální proměnné – deklarace proměnné s inicializací, která představuje prostředek.

• Výraz – výraz, jehož výsledkem je prostředek.

• Příkaz – příkaz, v němž se nesmí přiřadit jiná hodnota do proměnné deklarované v části získání prostředků.

Page 27: KST/ICSHP - 3. a 4. přednáška

Příkaz using • Příklad ekvivalentních konstrukcí

using (R r = new R()) { r.f(); }

R r = new R(); try { r.f(); } finally { if (r != null) ((IDisposable)r).Dispose(); }

Page 28: KST/ICSHP - 3. a 4. přednáška

Příkaz using • Je možné deklarovat i několik proměnných stejného typu

oddělených čárkou.

using (R r1 = new R(), r2 = new R()) { r1.f(); r2.f(); }

using (R r1 = new R()) { using (R r2 = new R()) { r1.f(); r2.f(); } }

Page 29: KST/ICSHP - 3. a 4. přednáška

Příkaz lock • Nemá v C++ obdobu. • Slouží k synchronizaci mezi podprocesy (threads) programu

pomocí vzájemně výlučných zámků – mutexů.

• Syntaxe lock (výraz) příkaz

• Příkaz lock získá pro daný objekt mutex, vyvolá příkaz a mutex uvolní.

Odkaz na referenční typ. Zde nedochází k zabalení

hodnotových typů.

Page 30: KST/ICSHP - 3. a 4. přednáška

Příkaz lock lock (x) { /* ... */ }

object obj = x; System.Threading.Monitor.Enter(obj); try { /* ... */ } finally { System.Threading.Monitor.Exit(obj); }

Přiřazení výrazu x do proměnné obj je zde proto, aby se výraz x

vyhodnotil pouze jednou.

Page 31: KST/ICSHP - 3. a 4. přednáška

Příkaz lock • Pro statické metody třídy se často jako zámek používá

instance třídy Type – získá se prostřednictvím operátoru typeof.

• Pro vyloučení současného volání přidej a odeber lze psát: class SynchronizovanýObjekt {

public static void Přidej(object x) { lock(typeof(SynchronizovanýObjekt)) { /* tělo metody */ } } public static void Odeber(object x) { lock(typeof(SynchronizovanýObjekt)) { /* tělo metody */ } }

}

Page 32: KST/ICSHP - 3. a 4. přednáška

Příkaz yield • V C++ neexistuje

• Používá se v iterátoru – viz dále.

Page 33: KST/ICSHP - 3. a 4. přednáška

Příkaz try • Podobně jako v C++ se jedná o pokusný blok Zachycení a ošetření výjimek – viz výjimky

Page 34: KST/ICSHP - 3. a 4. přednáška

Operátory a výrazy • Přehled operátorů Operátory se ve výrazu vyhodnocují na základě priority. Nejdříve se

vyhodnocují operátory s vyšší prioritou. Pokud má více operátorů stejnou prioritu, vyhodnocují se podle jejich asociativity.

Prioritu lze měnit pomocí kulatých závorek, ty mají nejvyšší prioritu.

• Binární operátory jsou asociativní zleva doprava. • Unární, přiřazovací, ternární a operátor nulového

sjednocení jsou asociativní zprava doleva.

Page 35: KST/ICSHP - 3. a 4. přednáška

Operátory a výrazy • Přehled operátorů http://msdn.microsoft.com/en-us/library/6a71f45d.aspx

Page 36: KST/ICSHP - 3. a 4. přednáška

Operátory • Poznámky: V C# se za operátor považují i () za účelem změny pořadí vyhodnocování.

V C++ jsou považovány za oddělovač.

V C# je operátor new operátorem volání konstruktoru. V C++ je alokátorem.

Praktický význam pro

programátora?

žádný!

V C# se alokace sturktur

neprovádí.

Page 37: KST/ICSHP - 3. a 4. přednáška

Operátory • Poznámky: V C# chybí oproti C++ některé operátory přetypování.

A také některé další operátory (např. pro třídní ukazatel)

static_cast, dynamic_cast,

reinterpret_cast a const_cast

.*, ->*,

typeid

Page 38: KST/ICSHP - 3. a 4. přednáška

Operátory • Poznámky: V C# lze některé operátory využít pouze v nezabezpečeném kódu.

stackalloc (alokace na zásobníku) sizeof (velikost hodnotového typu) -> (přístup ke složce struktury) * (dereferencování ukazatele) & (získání adresy)

Page 39: KST/ICSHP - 3. a 4. přednáška

Číselná rozšíření • Unární rozšíření Implicitní konverze uplatňující se pro předdefinované unární operátory +, - a ~

sbyte, byte, short, ushort a char se implicitně převádí na typ int uint se při použití minus převádí na long

Bitový doplněk

sbyte a = -1; a = -a; //Chyba, na rozdíl od C++ nelze implicitně konvertovat int na sbyte

Page 40: KST/ICSHP - 3. a 4. přednáška

Číselná rozšíření • Binární rozšíření Implicitní konverze obou operandů na společný typ (ten nebo bool bude

také typem výsledku) při použití předdefinovaných binárních operátorů +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=.

Pravidla 1. Pokud je první z operandů decimal, převede se druhý též na decimal.

Chyba nastane, pokud je druhý operand typu float nebo double, protože neexistuje implicitní konverze.

V případě relačních operátorů.

Page 41: KST/ICSHP - 3. a 4. přednáška

Číselná rozšíření • Binární rozšíření Pravidla

2. Pokud je jeden operand double, druhý se převede na double. 3. Pokud je jeden operand typu float, druhý se převede na float. 4. Je-li jeden z operandů typu ulong, převede se druhý na ulong, pokud není

sbyte, short, int nebo long (jinak chyba). 5. Pokud je jeden z operandů typu long, převede se druhý na long.

Page 42: KST/ICSHP - 3. a 4. přednáška

Číselná rozšíření • Binární rozšíření Pravidla

6. Pokud je jeden z operandu uint a druhý je typu sbyte, short nebo int, převedou se oba operandy na long.

7. Jinak, pokud je jeden z operandů typu uint, převede se druhý na uint. 8. Jinak se oba operandy převedou na int.

Page 43: KST/ICSHP - 3. a 4. přednáška

Některé operátory • Operátor tečka Specifikuje přístup ke statickým a nestatickým složkám tříd, struktur,

výčtových typů a jmenných prostorů. Nahrazuje ., -> a :: z C++

• Typeof Zjišťování typu Podobný význam jako typeid z C++ Typeof lze použít jen na jméno typu, nikoli na výraz. K tomu lze použít

metodu GetType().

if ((a + b).GetType() == typeof(int)) { /* ... */ }

Page 44: KST/ICSHP - 3. a 4. přednáška

Některé operátory • is Zjišťování typu Syntaxe

výraz is typ výraz – výraz referenčního typu typ – jméno typu třídy, struktury či rozhraní

Vrací true pokud lze výraz přetypovat na typ. Pro hodnotové typy lze operátor is použít, pokud je výraz typu object.

Page 45: KST/ICSHP - 3. a 4. přednáška

Některé operátory • Přetypování Na rozdíl od C++ se vždy kontroluje, zda má přetypování smysl. (typ)

Stejně jako v C++. Pokud je při kompilaci zjištěna nemožnost přetypování, ohlásí překladač chybu.

Pokud se tato nemožnost objeví až za běhu programu, dojde k vyvolání výjimky System.InvalidCastException

as K přetypování mezi referenčními typy. Syntaxe

výraz as typ

Page 46: KST/ICSHP - 3. a 4. přednáška

Některé operátory • Přetypování as

Syntaxe výraz as typ

výraz – reference na instanci, která se má přetypovat nebo hodnota, která se má zabalit.

typ – cílový referenční typ Je-li možné přetypování je výsledkem typ, jinak null.

static void Vypis(object r) { string s = r as string; if (s != null) Console.WriteLine(s); }

Page 47: KST/ICSHP - 3. a 4. přednáška

Některé operátory • Bitové posuny << a >>

Levý operand musí být celočíselného typu. Sbyte, byte, short, ushort a char se převádí na typ int.

Pravý operand musí být typu int nebo se na něj musí nechat implicitně zkonvertovat.

Výsledkem je hodnota typu levého operandu.

Page 48: KST/ICSHP - 3. a 4. přednáška

Některé operátory • Rovná se, nerovná se == a !=

Lze použít i k porovnání zda reference ukazují na stejný objekt. Např. u string přetíženo na porovnání obsahu. Pokud v době překladu je známo, že reference ukazují na různé instance,

překladač ohlásí chybu. Lze porovnávat instance delegátů. Jsou si rovny, jsou-li stejného typu a:

oba obsahují null, nebo ukazují na tutéž statickou či nestatickou metodu a stejný objekt

Mohou ukazovat na více stejných metod.

Page 49: KST/ICSHP - 3. a 4. přednáška

Některé operátory • Podmíněný operátor ?: Na rozdíl od C++ smí být první operand pouze bool, nebo typ, který lze

implicitně přetypovat na bool, nebo obsahuje operator true. Typ výsledku výrazu A ? X : Y je určen podle: Je-li typ X a typ Y stejný, bude tento i typem výsledku.

Existuje-li implicitní konverze z typu výrazu X na typ výrazu Y a neexistuje-

li implicitní konverze z Y na X, bude typem výsledku typ Y.

Existuje-li implicitní konverze z typu výrazu Y na typ výrazu X a neexistuje-li implicitní konverze z typu X na typ Y, bude typem výsledku typ X.

Jinak nelze typ výsledku určit a překladač oznámí chybu.

Page 50: KST/ICSHP - 3. a 4. přednáška

Preprocesor • V C# se hovoří o tzv. „direktivách preprocesoru“ – nezpracovává je

však preprocesor jako v C++, ale překladač.

• Podmíněné symboly Neexistují makra Symbol #define

Slouží k definování podmíněného symbolu Syntaxe

#define identifikátor

Page 51: KST/ICSHP - 3. a 4. přednáška

Preprocesor • Podmíněné symboly Symbol #define

Musí být v programu před všemi ostatními direktivami preprocesoru (tedy i před using).

Identifikátor je definován od #define do konce zdrojového souboru. Definice podmíněného symbolu pro všechny překládané části sestavení: menu

Project > Properties, část Build, pole Conditional compilation symbols.

#define LADĚNÍ using System; // další příkazy programu

Page 52: KST/ICSHP - 3. a 4. přednáška

Preprocesor • Podmíněné symboly Symbol #undef

Slouží ke zrušení podmíněného symbolu zavedeného direktivou #define nebo ve vlastnostech profilu

Musí být v programu před všemi ostatními direktivami, které nejsou direktivami preprocesoru

Page 53: KST/ICSHP - 3. a 4. přednáška

Preprocesor • Podmíněný překlad Pomocí symbolu #if, podobně jako v C++ Schéma #if podmíněný_výraz_1 zdrojový_text_1 #elif podmíněný_výraz_2 zdrojový_text_2 // ... #else zdrojový_text_n #endif

#elif se může opakovat

několikrát

#elif a #else lze vynechat

Page 54: KST/ICSHP - 3. a 4. přednáška

Preprocesor • Podmíněný překlad Nejjednodušší použití

#define LADĚNÍ // ... #if LADĚNÍ Console.WriteLine("x = " + x); #endif

Page 55: KST/ICSHP - 3. a 4. přednáška

Preprocesor • Podmíněný překlad Složitější podmíněné výrazy – mohou obsahovat ==, !=, &&, ||, konstanty true a false.

Na rozdíl od C++ nemohou podmíněné výrazy obsahovat číselné konstanty ani konstanty definované pomocí const.

#if LADĚNÍ == false Console.WriteLine("x = " + x); #endif #if (LADĚNÍ || TESTOVÁNÍ) Console.WriteLine("y = " + y); #endif

Page 56: KST/ICSHP - 3. a 4. přednáška

Preprocesor • Podmíněný překlad Pokud je program v prostředí Visual Studio překládán v ladícím režimu (v

poli Solution Configuration je zvolena položka Debug), je automaticky definován symbol DEBUG.

Page 57: KST/ICSHP - 3. a 4. přednáška

Preprocesor • Chybová hlášení Direktiva #error

Podobně jako v C++. Způsobí výpis chybové zprávy a zastaví překlad.

Direktiva #warning

Způsobí výpis chybového hlášení, avšak nezastaví překlad.

Chybové hlášení - zpráva bez uvozovek. Případné uvozovky

jsou součástí výstupu.

Obě direktivy lze použít pouze ve zdrojovém textu

direktivy #if.

Page 58: KST/ICSHP - 3. a 4. přednáška

Preprocesor • Oblast zdrojového kódu Direktivy #region a #endregion

Slouží k vymezení oblasti. V C++ neexistují Syntaxe

#region zprávanep #endregion zprávanep

Visual Studio umožňuje takto označené oblasti „skrýt“ (zabalit)

Nesmí se křížit, mohou se vnořovat

Nemění význam programu. Jen

označují oblast ve zdrojovém kódu.

Page 59: KST/ICSHP - 3. a 4. přednáška

Preprocesor • Řádkování Direktiva #line

Umožňuje při překladu změnit počítání řádků a název souboru. Stejné jako v C++ Syntaxe

#line číslo název_souborunep

číslo – celé číslo, které má překladač považovat za aktuální číslo řádku. název_souboru – jaké jméno souboru má překladač považovat za aktuální (bez

uvozovek)

Page 60: KST/ICSHP - 3. a 4. přednáška

Preprocesor • Pragma Direktiva #pragma

Ke specifikaci kontextových informací pro překladač Význam může být v různých překladačích odlišný Ve Visual Studio 2012:

#pragma warning – zapnutí či vypnutí určitého varování #pragma checksum – generování kontrolního součtu zdrojového souboru

/// <summary> /// Základní barvy. /// </summary> public enum Barva { #pragma warning disable 1591 červená, zelená, modrá #pragma warning restore 1591 }

Číselný seznam varování,

oddělených čárkou

Page 61: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Rozdíly mezi C++ a C# V C# není podporována vícenásobná (a tedy i virtuální) dědičnost V C# lze dědičnost u tříd zakázat Všechny třídy v C# mají společného předka – object V C# lze vytvářet pouze dynamické instance, o jejich dealokaci se stará

automatická správa paměti. Význam destruktoru je podstatně menší než v C++. Třídy mohou implementovat rozhraní Mohou obsahovat kromě datových složek, metod, konstruktorů a

destruktorů také vlastnosti, události, přetížené operátory a vnořené typy.

Page 62: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Základní informace Deklarace modifikátorynep partialnep class identifikátor předeknep tělo;nep

modifikátory - přístupová práva, uvádí se pro každou složku zvlášť, mohou dále obsahovat specifikaci abstract, sealed, new či static

identifikátor – jméno deklarované třídy předek – předek třídy a implementovaná rozhraní tělo - skupina deklarací ve složených závorkách; může však být i

prázdné modifikátor partial – definice částečné třídy Deklarace třídy nemůže být jako lokální typ (v metodě), ale jen v

prostoru jmen či v jiné třídě/struktuře (jako vnořený typ)

Page 63: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Základní informace Přístupová práva

Určují přístupnost složek v rámci třídy, v potomcích, v sestavení této třídy a v ostatních sestaveních

stupeň třída sestavení potomci ostatní public X X X X protected internal X X X protected X X internal X X private X

Page 64: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Základní informace Přístupová práva

private (soukromé složky) a protected (chráněné složky) – stejný význam jako v C++

public (veřejné složky) – pokud má třída jako celek modifikátor public, je pak daná složka veřejně přístupná všem sestavením.

internal (interní, vnitřní složky) – složka je přístupná všem součástem sestavení, v němž je třída definována.

protected internal – sjednocení přístupového práva internal a protected. Složka je přístupná jak ve tříde, v níž je deklarována, tak ve všech potomcích bez ohledu na sestavení.

Page 65: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Základní informace Přístupová práva

Není-li specifikátor přístupových práv uveden, jedná se o složku soukromou (private).

Datový typ složky nesmí mít širší přístupová práva než kterýkoli z dalších typů uvedených v deklaraci. Př.: potomek nesmí mít širší přístupová práva než předek. Př.: metoda nesmí mít širší přístupová práva, než typ, který vrací.

class A {} // je internal public class B { public A f() { /* ... */ } // Chyba }

internal vs.

public

Page 66: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Datové složky Deklarace je podobná deklaraci proměnných. Lze navíc použít atributy a modifikátory new a readonly. Statické a nestatické.

Page 67: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Datové složky Nestatické datové složky

Instance fields Složky jednotlivých instancí (stejně jako v C++) Třída může obsahovat datovou složku svého vlastního typu:

public class Prvek { private Prvek další; // OK // ... }

odkaz (ukazatel) na instanci

třídy

Page 68: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Datové složky Nestatické datové složky

Deklarace může obsahovat inicializaci

public class A { private int x = 10; private string s = "Text"; // ... }

Takovéto přiřazení hodnot proběhne ještě

před voláním konstruktoru

Pokud nedojde k inicializaci, inicializuje překladač před voláním konstruktoru hodnoty

na 0, false nebo null.

Page 69: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Datové složky Statické datové složky

Jako v C++ jsou společné pro všechny instance třídy. Existují již od zavedení třídy do paměti (tedy bez nutnosti existence instance). Deklarují se pomocí static. Ty statické datové složky, které nejsou inicializovány před voláním konstruktoru

(existují statické konstruktory), překladač inicializuje hodnotou 0, false nebo null.

Při použití mimo třídu je nutné je kvalifikovat jménem třídy.

Page 70: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Datové složky Neměnné datové složky

Konstanty Musí se inicializovat přímo v deklaraci Deklarace pomocí const

Je automaticky statická, static nelze použít Lze takto deklarovat hodnotové datové typy (základní typy), výčtový typ a string. Pro

referenční typy (třídy, …) jej lze použít pouze k deklaraci proměnné inicializované null. Deklarace pomocí readonly – složku lze inicializovat až konstruktorem, pak už

ji nelze měnit.

Page 71: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Datové složky Neměnné datové složky

Příklad: https://goo.gl/WdetzM

class A { const int x = 10; readonly int y = 20; public A(int y) { this.y = y; // OK x = 20; // Chyba }

public void Set(int y) { this.y = y; // Chyba }

}

Page 72: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Datové složky Neměnné datové složky

Příklad: https://goo.gl/eeckXC

struct Struktura { public int x; public void SetX(int x) { this.x = x; } } class Trida { public readonly int[] pole = new int[] {1, 2}; public readonly Struktura b; } class Program { static void Main(string[] args) { Trida a = new Trida(); a.pole[0] = 5; // OK //a.b.x = 20; // Chyba a.b.SetX(20); // OK } }

Page 73: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Datové složky Doporučení

Nestatické datové složky by se neměly deklarovat jako veřejné nebo chráněné. Přístup k nim pak realizovat pomocí vlastností.

Pro předdefinovanou instanci třídy nebo struktury, která neobsahuje metody, jež umožňují modifikovat její datové složky (angl. immutable type), se má deklarovat veřejná statická datová složka s modifikátorem readonly.

Page 74: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Odlišnosti od C++

Neexistuje obdoba inline metody. Vedle předávání parametrů hodnotou či odkazem existují v C# ještě tzv. výstupní

parametry. Metody v C# lze přetěžovat na základě způsobu předávání parametrů. Nelze předepsat implicitní hodnoty parametrů. Nelze využívat prototyp v těle třídy a deklaraci provést mimo. Ta musí být vždy v

těle třídy.

Page 75: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Odlišnosti od C++

Syntaxe modifikátorynep typ identifikátor ( seznam_parametrůnep ) tělo modifikátory – přístupová práva, vyjadřují, zda jde o statickou, virtuální,

abstraktní, zapečetěnou, předefinovanou, zastiňující metodu nebo externí metodu z klasické dynamické knihovny. Lze uvést též unsafe (nezabezpečený kód metody).

typ – typ návratové hodnoty. Možno i void. identifikátor - jmenovka metody. Nemusí být unikátní, pokud se liší

signatura.

Počet, pořadí, typ a způsob předávání

parametrů.

Page 76: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Odlišnosti od C++

Syntaxe modifikátorynep typ identifikátor ( seznam_parametrůnep ) tělo seznam_parametrů – seznam formálních parametrů metody. Možno vynechat. tělo - obvykle blok příkazů. U abstraktních a externích metod je tělo tvořeno

středníkem.

Page 77: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Nestatické metody Nestatické metody (angl. instance methods) implementují

operace s jednotlivými instancemi. Volají se pro konkrétní instanci. Jméno nestatické metody volané mimo její třídu se kvalifikuje jménem instance její třídy. V deklaraci není uveden modifikátor static. V těle metody je k dispozici odkaz na aktuální instanci

vyjádřený klíčovým slovem this, stejně jako v C++. Odkazem this lze kvalifikovat pouze nestatické složky třídy.

Page 78: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Nestatické metody Příklad

class TridaA { int a; TridaA(int a) {

this.a = a; }

}

Page 79: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Statické metody

Statická metoda se deklaruje s modifikátorem static Implementují operace s třídou jako celkem, ne instancemi. Není k dispozici this a nelze pracovat s nestatickými složkami bez kvalifikace

instance.

Page 80: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Statické metody

Příklad

class Program { void Run() // nestatická metoda { Console.WriteLine("Zavolána nestatická metoda Run"); } static void Main(string[] args) // statická metoda { Program program = new Program(); program.Run(); } }

Page 81: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Předávání parametrů

V C# lze předávat parametry metody hodnotou nebo odkazem a používat výstupní parametry. Lze také deklarovat metodu s proměnným počtem parametrů - obdoba výpustky v C++.

Syntaxe typ identifikátor

Typ – typ parametru. Identifikátor – jméno parametru.

Page 82: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Předávání parametrů hodnotou

Význam parametru předávaného hodnotou je stejný jako v C++ - vytváří se lokální proměnná v těle metody, do které se uloží hodnota skutečného parametru.

V případě hodnotových parametrů se skutečný parametr nemění. U referenčních typů se předává odkaz na instanci -> může dojít ke změně datové složky

odpovídající instance. Skutečným parametrem může být jakýkoli výraz, který lze implicitní konverzí převést na

typ parametru.

Page 83: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Předávání parametrů hodnotou

Příklad: https://goo.gl/tk5ReL

class TridaA { public int x, y; public TridaA(int x, int y) { this.x = x; this.y = y; } } struct StrukturaB { public int x, y; public StrukturaB(int x, int y) { this.x = x; this.y = y; } } class Program { static void f(TridaA a1, TridaA a2, StrukturaB b) { a1.x = b.x; // složka x se ve skutečném parametru změní a2 = a1; // skutečný parametr se nezmění b.y = a1.y; // skutečný parametr se nezmění } static void Main(string[] args) { TridaA a1 = new TridaA(10, 20), a2 = new TridaA(30, 40); StrukturaB b = new StrukturaB(50, 60); f(a1, a2, b); // změna pouze u složky a1.x = 50 } }

Page 84: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Předávání parametrů odkazem

Význam předávání parametru odkazem je stejný jako v C++, syntaxe je ovšem jiná – před typ se zapisuje modifikátor ref.

Syntaxe ref typ identifikátor

Formální parametr v metodě představuje vlastně jen jiné jméno pro skutečný parametr, takže veškeré operace prováděné s formálním parametrem se ihned projeví v hodnotě skutečného parametru. Při volání metody se před skutečný parametr musí zapsat

modifikátor ref. Skutečným parametrem musí být proměnná stejného typu,

jaký je uveden v deklaraci formálního parametru nebo typu, který je potomkem typu formálního parametru.

Page 85: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Předávání parametrů odkazem Příklad

class Program { static void g(ref TridaA a1, ref TridaA a2, ref StrukturaB b) { a1.x = b.x; a2 = a1; // a2 se bude odkazovat na a1 b.y = a1.y; } static void Main(string[] args) { TridaA a1 = new TridaA(10, 20), a2 = new TridaA(30, 40); StrukturaB b = new StrukturaB(50, 60); g(ref a1, ref a2, ref b); // všechny instance mají složky x = 50, y = 20 Console.ReadLine(); } }

Page 86: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Výstupní parametry Výstupní parametry se liší od parametrů předávaných

hodnotou tím, že jako skutečný výstupní parametr lze předat proměnnou, která nebyla inicializována. V metodě se musí výstupní parametr inicializovat, i když byl skutečný parametr před voláním této metody inicializován. Před formálním i skutečným parametrem se musí zapsat

modifikátor out. Syntaxe

out typ identifikátor

Page 87: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Výstupní parametry Příklad

class Program { static void f(int x, out int y) { // Console.WriteLine("y = " + y); // Chyba - y není inicializ. y = x; Console.WriteLine("y = " + y); // OK } static void Main(string[] args) { int x = 20, y; f(x, out y); // proměnná x musí být inicializována } }

Page 88: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Neznámý počet parametrů

Jestliže předem není známý počet a typ parametrů metody, lze v C# použít modifikátor params. Tento modifikátor lze použít u posledního z formálních parametrů metody. V normě C# se tento parametr nazývá parameter array.

Syntaxe params typ_pole identifikátor

Typ pole – typ jednorozměrného pole. Nelze v něm použít modifikátory ref a out.

Skutečným parametrem může být: Pole odpovídajícího typu – parametr s modifikátorem params se chová

stejně jako parametr předávaný hodnotou. Seznam výrazů oddělených čárkou, jejichž hodnoty lze implicitními

konverzemi převést na typ prvků pole formálního parametru.

Page 89: KST/ICSHP - 3. a 4. přednáška

TŘÍDY • Metody Neznámý počet parametrů

class Matematika { public static int Maximum(params int[] data) { if (data.Length == 0) return 0; int max = data[0]; foreach (int a in data) { if (a > max) max = a; } return max; } } class Program { static void Main(string[] args) { Console.WriteLine("Maximum = {0}", Matematika.Maximum(5, 88, -3)); int[] pole = { 9, 8, 7 }; int max = Matematika.Maximum(pole); Console.WriteLine("Maximum = {0}", max); } }

Page 90: KST/ICSHP - 3. a 4. přednáška

• Metody Přetěžování V C# lze deklarovat v jedné třídě metody se stejným

identifikátorem, pokud se liší v počtu, typu, pořadí nebo způsobu předávání parametrů.

Lze deklarovat void f() {}

void f(int x) {}

void f(char x) {}

void f(ref char x) {}

void f(char x) {}

void f(out char x) {}

TŘÍDY

Page 91: KST/ICSHP - 3. a 4. přednáška

• Metody Přetěžování Nelze deklarovat metody lišící se jen ref a out.

void f(ref char x) {}

void f(out char x) {} //chyba

Nelze rozlišit metody pouze podle typu návratové hodnoty nebo podle modifikátoru params.

Pokud skutečné parametry neodpovídají, používají se pravidla pro nalezení „nejlepší shody“. stejný počet parametrů + nejsnažší implicitní konverze typů skutečných na

formální typy metody.

TŘÍDY

Page 92: KST/ICSHP - 3. a 4. přednáška

• Metody - doporučení Výstupní parametry vždy uvádět až na konci seznamu parametrů metody

(kromě parametrů s modifikátorem params)

Přetížené metody by měly mít parametry stejného typu a názvu uvedené ve stejném pořadí (kromě těch s modifikátory out a params, které by měly být na konci).

TŘÍDY

Page 93: KST/ICSHP - 3. a 4. přednáška

• Metody - doporučení Pokud mají být přetížené metody virtuální, má být deklarována jako

virtuální pouze jedna verze přetížené metody, která má největší počet parametrů. Ostatní verze metody, by měly volat tuto verzi.

TŘÍDY

public void Write(string message, FileStream stream) { this.Write(message, stream, false); } public virtual void Write(string message, FileStream stream, bool closeStream) { // vlastní činnost }

Page 94: KST/ICSHP - 3. a 4. přednáška

• Metody – doporučení Pokud některý parametr metody je volitelný, měly by se vytvořit dvě

přetížené verze této metody, jedna s tímto parametrem a druhá bez tohoto parametru.

Parametr referenčního typu, pro který je povolena hodnota null by se neměl chápat jako volitelný parametr, ale jako parametr, pro nějž se má použít nějaká implicitní hodnota.

TŘÍDY

Page 95: KST/ICSHP - 3. a 4. přednáška

• Externí metody V C# lze volat i funkce napsané v C/C++ nebo v jiném programovacím

jazyce a uložené v klasické dynamické knihovně pro neřízený kód. Tato funkce musí být deklarována v C# jako statická externí metoda s atributem DllImport, ve kterém se uvede jméno souboru dynamické knihovny.

Takto lze volat i funkce z Windows API. Syntaxe

[DllImport( knihovna )] modifikátorynep static extern typ identifikátor (seznam_parametrůnep);

TŘÍDY

Page 96: KST/ICSHP - 3. a 4. přednáška

• Externí metody Příklad

TŘÍDY

class Program { [DllImport("user32.dll")] static extern int MessageBox(int windowHandle, string text, string caption, uint type); static void Main(string[] args) { MessageBox(0, "Ukázka volání funkce MessageBox z Windows API", "Hlášení", 0); } }

Page 97: KST/ICSHP - 3. a 4. přednáška

• Metoda Main Vstupní bod konzolové i okenní aplikace. Má 4 podoby: static int Main() {} static int Main(string[] args) {} static void Main() {} static void Main(string[] args) {}

Libovolný specifikátor přístupových práv. Pokud je návratový typ int, vrací kód ukončení programu – jako v C++

TŘÍDY

Page 98: KST/ICSHP - 3. a 4. přednáška

• Metoda Main Parametr args představuje parametry předávané z příkazové řádky.

Na rozdíl od C++ není nultým parametrem název programu. Lze ji přetěžovat, ale jako vstupní bod může sloužit jen jedna z výše

uvedených. Může se nacházet ve více třídách – nutno ale určit, která se použije jako

vstupní bod programu. pomocí přepínače: /main:třída pomocí menu: Project | Properties, část Application, rozevírací seznam Startup

object

TŘÍDY

Page 99: KST/ICSHP - 3. a 4. přednáška

• Podmíněné metody Metodu s návratovým typem void lze deklarovat jako podmíněnou s

atributem Conditional. Syntaxe

[ Conditional ( "jméno" ) ] deklarace_metody_typu_void Jméno – identifikátor podmíněného symbolu deklarovaného pomocí direktivy #define. Je-li identifikátor jméno definován, přeloží se tato metoda i všechna její volání stejně, jako

kdyby atribut Conditional nebyl u metody uveden. Pokud identifikátor jméno není definován, překladač odstraní všechna volání této metody

ze zdrojových textů programu, ale metodu přeloží.

TŘÍDY

Page 100: KST/ICSHP - 3. a 4. přednáška

• Podmíněné metody Příklad

TŘÍDY

#define LADĚNÍ using System; using System.Diagnostics; class Ladění { [Conditional("LADĚNÍ")] public static void Výpis(string s, int x) { Console.WriteLine("Proměnná {0} má hodnotu {1}", s, x); } } class Program { static void Main(string[] args) { int a = 1, b = 2; Ladění.Výpis("a", a); // #1 Ladění.Výpis("b", b); // #2 Console.WriteLine("Součet proměnných je {0}", a + b); Console.ReadKey(); } }

Page 101: KST/ICSHP - 3. a 4. přednáška

• Konstruktory Podobně jako v C++ slouží k vytvoření a inicializaci instance. Rozdíly oproti C++

V C# lze deklarovat statické konstruktory V C# může konstruktor volat jiný konstruktor téže třídy Konstruktor v C# nelze použít k implicitní konverzi V C# neexistuje kopírovací konstruktor V C# je konstruktor volán vždy explicitně pomocí new

TŘÍDY

Page 102: KST/ICSHP - 3. a 4. přednáška

• Konstruktory instanční konstruktor

známý z C++ Syntaxe

modifikátorynep identifikátor ( seznam_parametrůnep ) inicializátornep tělo Inicializátor

:this (seznam_parametrůnep) :base (seznam_parametrůnep)

Modifikátory – přístupová práva Identifikátor – shodný s názvem třídy, které je konstruktorem

TŘÍDY

Volání jiného konstruktoru téže třídy

Volání konstruktoru bezprostředního předka třídy

Page 103: KST/ICSHP - 3. a 4. přednáška

• Konstruktory instanční konstruktor

nedědí se Pokud neexistuje uživatelem definovaný konstruktor, vytváří překladač

implicitní, veřejně přístupný konstruktor bez parametrů a s prázdným tělem.

TŘÍDY

Page 104: KST/ICSHP - 3. a 4. přednáška

• Konstruktory instanční konstruktor

Příklad: https://goo.gl/bk5T9P

TŘÍDY

class Matice { double[,] a; public Matice(int m, int n) { a = new double[m, n]; } public Matice(int m, int n, double hodnota) : this(m, n) { for (int i = 0; i < a.GetLength(0); i++) { for (int j = 0; j < a.GetLength(1); j++ ) a[i, j] = hodnota; } } public void Výpis() { ... } } class Program { static void Main(string[] args) { Matice matice = new Matice(3, 2); matice.Výpis(); matice = new Matice(3, 2, 10.54); matice.Výpis(); // Matice matice2 = new Matice(); // Chyba - třída nemá implicitní konstruktor } }

Page 105: KST/ICSHP - 3. a 4. přednáška

• Konstruktory instanční konstruktor

doporučení parametr konstruktoru vlastnosti (a jí případně odpovídající datové složky) by měl mít

stejný název jako vlastnost – rozdíl je pouze ve velikosti písmen. Parametr velbloudím a veřejná/chráněná vlastnost pascalovským stylem.

TŘÍDY

Page 106: KST/ICSHP - 3. a 4. přednáška

• Konstruktory statický konstruktor

Neexistuje v C++ Slouží k inicializaci statických složek Syntaxe

static identifikátor ( ) tělo identifikátor – shodný s názvem třídy V těle (bloku příkazů) lze pracovat jen se statickými složkami třídy

Nedědí se Nelze jej volat explicitně (volá jej program při zavedení třídy do paměti)

TŘÍDY

Page 107: KST/ICSHP - 3. a 4. přednáška

• Konstruktory statický konstruktor

Nemá modifikátor přístupových práv Neobsahuje parametry

TŘÍDY

Page 108: KST/ICSHP - 3. a 4. přednáška

• Konstruktory statický konstruktor

Příklad

TŘÍDY

class Matice { double[,] a; static readonly int rozměr; static Matice() { Console.Write("Zadej rozměr matice: "); rozměr = Convert.ToInt32(Console.ReadLine()); } public Matice() { // rozměr = 3; // Chyba a = new double[rozměr, rozměr]; } public Matice(double hodnota) : this() { for (int i = 0; i < rozměr; i++) { for (int j = 0; j < rozměr; j++) a[i, j] = hodnota; } } // ... }

Page 109: KST/ICSHP - 3. a 4. přednáška

• Destruktor V nové normě C# je nazýván finalizér (finalizer). Jiná úloha než v C++ V C# jde o zkratku metody finalize třídy object. Tu volá automatická

správa paměti při uvolnění instance z paměti. Destruktor lze využít tedy např. k uvolnění jiných prostředků než je

operační paměť (otevřené soubory, síťová připojení) Syntaxe

~ identifikátor ( ) tělo identifikátor třídy, v němž je konstruktor deklarován

TŘÍDY

Page 110: KST/ICSHP - 3. a 4. přednáška

• Destruktor Nemá přístupová práva Nemá parametry Nedědí se Nelze jej volat explicitně V C# se používají zřídka

V rozsáhlejších programech mohou způsobovat zdržení při automatickém úklidu paměti. Objekty s destruktory nejsou odstraněny přímo, ale odkládají se stranou, pak se volá jejich finalize metoda, a pak se teprve odstraňují.

Destruktory se zpravidla kombinují s metodou Dispose() rozhraní IDisposable

TŘÍDY

Page 111: KST/ICSHP - 3. a 4. přednáška

• Vlastnosti (properties) V normě C++ neexistují. Lze se s nimi setkat v rámci některých rozšířeních

jazyka C++ (Borland C++ Builder). Syntaktická zkratka pro dvojici přístupových metod. Používá se prostřednictvím svého identifikátoru. Přiřazením hodnoty do

identifikátoru se volá jedna z přístupových metod. Ta může např. uložit danou hodnotu do soukromé datové složky či provést i řadu jiných operací.

Při použití hodnoty vlastnosti se volá druhá z metod. Ta může vrátit hodnotu uloženou v soukromé datové složce či hodnotu získanou např. výpočtem.

TŘÍDY

Page 112: KST/ICSHP - 3. a 4. přednáška

• Vlastnosti (properties) Syntaxe modifikátorynep typ jméno { část_set část_getnep } modifikátorynep typ jméno { část_get část_setnep }

Modifikátory - modifikátory přístupových práv a modifikátory vyjadřující, zda jde o statickou, virtuální, abstraktní, zapečetěnou, předefinovanou nebo zastiňující vlastnost.

Typ – typ hodnoty vlastnosti Jméno – identifikátor vlastnosti Část_set – přístupová metoda pro nastavení hodnoty vlastnosti Část_get – přístupová metoda pro zjištění hodnoty

TŘÍDY

Page 113: KST/ICSHP - 3. a 4. přednáška

• Vlastnosti (properties) Na pořadí uvedení části get a části set nezáleží.

Jednu z nich lze vynechat. Vynecháním části set se získá vlastnost „jen pro čtení“. Vynecháním části set se získá vlastnost „jen pro zápis“. Syntaxe částí get a set

modifikátorynep get tělo modifikátorynep set tělo

Tělo – blok příkazů, nebo jen středník u abstraktní vlastnosti. Modifikátory - Jsou-li modifikátory u dané části uvedeny, musí reprezentovat

přístupové právo, které více omezuje přístup k dané části než modifikátory přístupových práv pro vlastnost jako celek.

TŘÍDY

Page 114: KST/ICSHP - 3. a 4. přednáška

• Vlastnosti (properties) Modifikátory přístupových práv

TŘÍDY

Ve vlastnosti Povolené mod. u get a set public protected internal

internal protected private

protected internal internal protected private

internal private

protected private

private

Page 115: KST/ICSHP - 3. a 4. přednáška

• Vlastnosti (properties) V těle části set existuje proměnná value typu shodného

s typem vlastnosti. value obsahuje hodnotu přiřazovanou vlastnosti

Tělo části get musí obsahovat příkaz return výraz; ten poskytuje vrácenou hodnotu vlastnosti

TŘÍDY

Page 116: KST/ICSHP - 3. a 4. přednáška

• Vlastnosti (properties) Příklad: https://goo.gl/i8pzgB

TŘÍDY

class KomplexCislo { private int real; private int imag; public KomplexCislo(int real, int imag) { this.real = real; this.imag = imag; } public int Real { get { return real; } set { real = value; } } public int Imag { get { return imag; } set { imag = value; } } public double Abs { get { return Math.Sqrt(Real*Real + Imag*Imag); } } } class Program { static void Main(string[] args) { KomplexCislo kc = new KomplexCislo(10, 20); Console.WriteLine("Absolutní hodnota čísla ({0} + {1}i) je {2:F1}", kc.Real, kc.Imag, kc.Abs); kc.Real = 3; kc.Imag = 4; Console.WriteLine("Absolutní hodnota čísla ({0} + {1}i) je {2:F1}", kc.Real, kc.Imag, kc.Abs); Console.ReadKey(); } }

Page 117: KST/ICSHP - 3. a 4. přednáška

• Vlastnosti (properties) Statické vlastnosti Statická vlastnost je deklarována s modifikátorem static. Lze ji použít, i v případě, že neexistuje žádná instance dané

třídy. Při použití statické vlastnosti mimo její třídu se kvalifikuje

jménem její třídy. Část get a část set statické vlastnosti může pracovat pouze

se statickými složkami dané třídy.

TŘÍDY

Page 118: KST/ICSHP - 3. a 4. přednáška

• Vlastnosti (properties) Doporučení Vlastnost by měla mít stejný název jako její odpovídající datová

složka. Rozdíl je pouze ve velikosti písmen. Pro soukromou datovou

složku se používá velbloudí styl a pro veřejnou a chráněnou vlastnost pascalovský styl.

Pokud se jedná o řádově pomalejší operaci, než je nastavení hodnoty do datové složky třídy (např. přístup k souboru), doporučuje se použít místo vlastnosti metodu.

Nedoporučuje se deklarovat vlastnosti, které umožňují pouze nastavení hodnoty (to lze provést metodou).

Nastavení vlastností dané třídy by nemělo být závislé na pořadí. Pokud při nastavení vlastnosti dojde k vyvolání výjimky, měla by

si vlastnost uchovat předchozí hodnotu. Část get by neměla vyvolávat výjimku.

TŘÍDY

Page 119: KST/ICSHP - 3. a 4. přednáška

• Události Jazyk C# oproti C++ nabízí jednotný mechanismus zpracování událostí.

Založeno na návrhovém vzoru vydavatel – předplatitel (publisher - subscriber). Instance, v níž může událost vzniknout (vydavatel), si vede

seznam instancí, jež mají zájem na tuto událost reagovat (předplatitelů).

Instance, jež má zájem reagovat na určitou událost, tedy předplatitel, si u vydavatele registruje metodu, která se o reakci postará. K tomu použije delegát.

Nastane-li událost, vyrozumí o ní vydavatel své předplatitele tím, že zavolá jejich registrované metody.

TŘÍDY

Page 120: KST/ICSHP - 3. a 4. přednáška

• Události Handler a údaje o události Metody, které reagují na události, se označují jako handlery.

Jsou vždy typu void. Mají dva parametry (object – odkaz na instanci jež vyvolala událost a System.EventArgs).

Signatura void Stisk(object sender, EventArgs e) {}

Knihovna BCL obsahuje řadu potomků třídy EventArgs pro běžné typy událostí, jako je stisknutí tlačítka myši, stisknutí klávesy apod.

Pokud událost umožňuje stornování činnosti, druhý parametr handleru by měl být typu CancelEventArgs (nebo jeho potomek). Typ CancelEventArgs obsahuje jednu vlastnost Cancel, která poskytuje nebo nastavuje hodnotu, udávající, zda činnost, která je s událostí spojená, by měla být stornována.

TŘÍDY

Page 121: KST/ICSHP - 3. a 4. přednáška

• Události Handler a údaje o události Pro zpracování událostí nabízí knihovna BCL celou řadu

předdefinovaných delegátů. Lze si však deklarovat i vlastní. Identifikátor delegátu by měl obsahovat příponu EventHandler. Potomek třídy EventArgs by měl obsahovat příponu EventArgs.

Delegát může obsahovat ukazatele na více handlerů.

TŘÍDY

delegate void NecoSeStaloEventHandler(object sender, MojeEventArgs e);

Page 122: KST/ICSHP - 3. a 4. přednáška

• Události Deklarace události

Jako složka třídy Syntaxe modifikátorynep event typ jméno ; modifikátorynep event typ jméno { části_add_remove }

Modifikátory – modifikátory přístupových práv a modifikátory vyjadřující, zda jde o statickou, virtuální, abstraktní, zapečetěnou, předefinovanou nebo zastiňující událost. Typ – identifikátor delegátu. Jméno – jméno (identifikátor) události. Zpravidla odpovídá

identifikátoru typ bez přípony EventHandler.

TŘÍDY

Page 123: KST/ICSHP - 3. a 4. přednáška

• Události Deklarace události Klíčové slovo event zamezí vyvolání události mimo třídu, v níž je

událost deklarována. Mimo třídu události lze používat pouze operátory += a -= pro

registraci/zrušení registrace handleru. Událost je tedy vícenásobný delegát, který nelze zavolat mimo jeho

třídu. Událost by měla vyvolávat chráněná virtuální metoda třídy, v níž je

událost deklarována. Název této metody by měl být ve tvaru OnJmeno, kde Jmeno je jméno

události. Ta má jeden parametr odpovídající druhému parametru události (typu EventArgs, případně jeho potomka).

První parametr vyvolané události by neměl mít hodnotu null, kromě statické události. Druhý parametr by neměl být nikdy null. Třída EventArgs nabízí statickou datovou složku jen pro čtení Empty, která by se měla použít místo vytvoření nové instance této třídy.

TŘÍDY

Page 124: KST/ICSHP - 3. a 4. přednáška

• Události – Příklad: https://goo.gl/D5YlSk

TŘÍDY public delegate void ZmenaSouradnicEventHandler(object sender, EventArgs e); class Bod { private int x; private int y; public event ZmenaSouradnicEventHandler ZmenaSouradnic; public int X { get { return x; } set { if (x != value) { x = value; OnZmenaSouradnic(EventArgs.Empty); } } } public int Y { get { return y; } set { if (y != value) { y = value; OnZmenaSouradnic(EventArgs.Empty); } } } public Bod(int x, int y) { this.x = x; this.y = y; } protected virtual void OnZmenaSouradnic(EventArgs e) { ZmenaSouradnicEventHandler handler = ZmenaSouradnic; if (handler != null) handler(this, e); } } class Obrazek { public static void ZmenaSouradnic(object sender, EventArgs e) { Console.WriteLine("Došlo ke změně souřadnic bodu"); Console.WriteLine("Nové souřadnice bodu jsou: x = {0}, y = {1}", (sender as Bod).X, (sender as Bod).Y); } }

class Program { static void Main(string[] args) { Bod bod = new Bod(10, 20); bod.ZmenaSouradnic += new ZmenaSouradnicEventHandler(Obrazek.ZmenaSouradnic); // dtto od verze .NET 2.0: // bod.ZmenaSouradnic += Obrazek.ZmenaSouradnic; bod.X = 30; // Chyba - nelze volat událost mimo její třídu: // bod.ZmenaSouradnic(typeof(Program), new EventArgs()); Console.ReadKey(); } }

Page 125: KST/ICSHP - 3. a 4. přednáška

• Události - Příklad V metodě OnZmenaSouradnic je vytvořena kopie události, aby nevznikla

kolize při přístupu k události z více podprocesů. Pokud by se nevytvořila kopie, tak by po vyhodnocení výrazu v příkazu if, který testuje zda událost není null, mohl jiný podproces zrušit registraci handleru této události a pokud se jednalo o jediného předplatitele události, událost by měla hodnotu null a při jejím vyvolání by vznikla výjimka typu System.NullReferenceException. Lokální kopie události se sice odkazuje na stejnou instanci vícenásobného delegátu, ale pokud se k události registruje další handler, lokální kopie se již bude odkazovat na jinou instanci.

TŘÍDY

Page 126: KST/ICSHP - 3. a 4. přednáška

• Události jako vlastnosti Obsahuje-li třída větší množství událostí a jejich handlerů, může být

rozumné deklarovat je jako vlastnosti. Umožňuje použít vlastní způsob ukládání handlerů, např. do hešovací

tabulky nebo jiné kolekce. Událost se deklaruje jako vlastnost také v případě, pokud je potřebné

ošetřovat volání každého zaregistrovaného handleru zvlášť. Syntaxe

add blok //přístupová metoda pro přidání handleru do kolekce handlerů remove blok //přístupová metoda pro odebrání handleru z kolekce handlerů

TŘÍDY

Page 127: KST/ICSHP - 3. a 4. přednáška

• Události jako vlastnosti – příklad: https://goo.gl/bNKlxD

TŘÍDY

class Bod { private int x; private int y; private ZmenaSouradnicEventHandler zmenaSouradnic; public event ZmenaSouradnicEventHandler ZmenaSouradnic { add { lock (this) zmenaSouradnic += value; } remove { lock (this) zmenaSouradnic -= value; } } protected virtual void OnZmenaSouradnic(EventArgs e) { ZmenaSouradnicEventHandler handler = zmenaSouradnic; if (handler != null) handler(this, e); } // zbytek stejný jako v předchozím příkladu