SlideShare une entreprise Scribd logo
1  sur  127
Télécharger pour lire hors ligne
Jazyk C#
Přednáška 03/04 – příkazy, operátory, OOP – třídy, vlastnosti,
události
Jan Hřídel
Jan.Hridel@upce.cz
• twitter: @h0nza
Myšlenka týdne
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).
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
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.
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,
…
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ů.
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.
Příkazy – základní konstrukce
• Deklarace
 Plnohodnotný příkaz – může se objevit kdekoli mezi ostatními příkazy.
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.
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 :
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í.
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 "":
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
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.
Cykly
• do-while
 Syntaxe
 do příkaz while (podmínka)
Platí totéž co
pro podmínku
příkazu if.
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
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.
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.
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.
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++
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.
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
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
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ů.
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();
}
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();
}
}
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ů.
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.
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 */ }
}
}
Příkaz yield
• V C++ neexistuje
• Používá se v iterátoru – viz dále.
Příkaz try
• Podobně jako v C++ se jedná o pokusný blok
 Zachycení a ošetření výjimek – viz výjimky
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.
Operátory a výrazy
• Přehled operátorů
 http://msdn.microsoft.com/en-us/library/6a71f45d.aspx
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í.
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
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)
Čí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
Čí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ů.
Čí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.
Čí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.
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)) { /* ... */ }
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.
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
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);
}
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.
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.
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.
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
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
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
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
Preprocesor
• Podmíněný překlad
 Nejjednodušší použití
#define LADĚNÍ
// ...
#if LADĚNÍ
Console.WriteLine("x = " + x);
#endif
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
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.
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.
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.
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)
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
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.
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)
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
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í.
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
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é.
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
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.
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.
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.
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
}
}
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
}
}
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.
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.
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ů.
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.
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.
TŘÍDY
• Metody
 Nestatické metody
 Příklad
class TridaA
{
int a;
TridaA(int a)
{
this.a = a;
}
}
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.
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();
}
}
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.
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.
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
}
}
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.
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();
}
}
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
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
}
}
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.
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);
}
}
• 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
• 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
• 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
• 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
}
• 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
• 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
• 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);
}
}
• 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
• 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
• 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
• 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();
}
}
• 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
• 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
• 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
• 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
}
}
• 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
• 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
• Konstruktory
 statický konstruktor
 Nemá modifikátor přístupových práv
 Neobsahuje parametry
TŘÍDY
• 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;
}
}
// ...
}
• 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
• 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
• 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
• 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
• 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
• 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
• 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
• 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();
} }
• 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
• 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
• 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
• 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
• 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);
• 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
• 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
• 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.ZmenaSou
radnic);
// 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();
}
}
• 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
• 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
• 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

Contenu connexe

Tendances

Java – Annotations
Java – AnnotationsJava – Annotations
Java – AnnotationsMartin Majlis
 
Tv 08
Tv 08Tv 08
Tv 08352
 
Tv 10 11
Tv 10 11Tv 10 11
Tv 10 11352
 
Tv 09
Tv 09Tv 09
Tv 09352
 
Tv 07
Tv 07Tv 07
Tv 07352
 
Zend_Db_Statement a Zend_Db_Profiler
Zend_Db_Statement a Zend_Db_ProfilerZend_Db_Statement a Zend_Db_Profiler
Zend_Db_Statement a Zend_Db_ProfilerOndrej Flidr
 
Zend_Db a Zend_Db_Adapter
Zend_Db a Zend_Db_AdapterZend_Db a Zend_Db_Adapter
Zend_Db a Zend_Db_AdapterOndrej Flidr
 
Seminar Nastroje Jednotk Testovani
Seminar Nastroje Jednotk TestovaniSeminar Nastroje Jednotk Testovani
Seminar Nastroje Jednotk TestovaniJakub Holy
 
Na co si dát v Javascriptu pozor? - Barcamp Hradec Králové 2015
Na co si dát v Javascriptu pozor? - Barcamp Hradec Králové 2015Na co si dát v Javascriptu pozor? - Barcamp Hradec Králové 2015
Na co si dát v Javascriptu pozor? - Barcamp Hradec Králové 2015angular-cz
 

Tendances (9)

Java – Annotations
Java – AnnotationsJava – Annotations
Java – Annotations
 
Tv 08
Tv 08Tv 08
Tv 08
 
Tv 10 11
Tv 10 11Tv 10 11
Tv 10 11
 
Tv 09
Tv 09Tv 09
Tv 09
 
Tv 07
Tv 07Tv 07
Tv 07
 
Zend_Db_Statement a Zend_Db_Profiler
Zend_Db_Statement a Zend_Db_ProfilerZend_Db_Statement a Zend_Db_Profiler
Zend_Db_Statement a Zend_Db_Profiler
 
Zend_Db a Zend_Db_Adapter
Zend_Db a Zend_Db_AdapterZend_Db a Zend_Db_Adapter
Zend_Db a Zend_Db_Adapter
 
Seminar Nastroje Jednotk Testovani
Seminar Nastroje Jednotk TestovaniSeminar Nastroje Jednotk Testovani
Seminar Nastroje Jednotk Testovani
 
Na co si dát v Javascriptu pozor? - Barcamp Hradec Králové 2015
Na co si dát v Javascriptu pozor? - Barcamp Hradec Králové 2015Na co si dát v Javascriptu pozor? - Barcamp Hradec Králové 2015
Na co si dát v Javascriptu pozor? - Barcamp Hradec Králové 2015
 

Similaire à KST/ICSHP - 3. a 4. přednáška

Jan Čislinský: Seznámení se Sourcery aneb Základy metaprogramování ve Swiftu
Jan Čislinský: Seznámení se Sourcery aneb Základy metaprogramování ve SwiftuJan Čislinský: Seznámení se Sourcery aneb Základy metaprogramování ve Swiftu
Jan Čislinský: Seznámení se Sourcery aneb Základy metaprogramování ve Swiftumdevtalk
 
Czjug Zari 2008
Czjug Zari 2008Czjug Zari 2008
Czjug Zari 2008RENESTEIN
 
TPL - konkurenční, paralelní a asynchronní kód pro náročné
TPL - konkurenční, paralelní a asynchronní kód pro náročnéTPL - konkurenční, paralelní a asynchronní kód pro náročné
TPL - konkurenční, paralelní a asynchronní kód pro náročnéRené Stein
 
Tv 06
Tv 06Tv 06
Tv 06352
 
.NET v SQL Serveru
.NET v SQL Serveru.NET v SQL Serveru
.NET v SQL ServeruJan Drozen
 
INPTP Rekapitulace
INPTP Rekapitulace INPTP Rekapitulace
INPTP Rekapitulace Jan Hřídel
 
Dependency injection v .Net Frameworku
Dependency injection v .Net FrameworkuDependency injection v .Net Frameworku
Dependency injection v .Net FrameworkuRené Stein
 
Péhápkaři - Píšeme čitelný kód #4 by Petr Bechyně, Driveto
Péhápkaři - Píšeme čitelný kód #4 by Petr Bechyně, DrivetoPéhápkaři - Píšeme čitelný kód #4 by Petr Bechyně, Driveto
Péhápkaři - Píšeme čitelný kód #4 by Petr Bechyně, DrivetoPetr Bechyně
 
Péhápkaři - Píšeme čitelný kód #2 by Petr Bechyně, Driveto
Péhápkaři - Píšeme čitelný kód #2 by Petr Bechyně, DrivetoPéhápkaři - Píšeme čitelný kód #2 by Petr Bechyně, Driveto
Péhápkaři - Píšeme čitelný kód #2 by Petr Bechyně, DrivetoPetr Bechyně
 
Grafy, zobrazení, vzorce
Grafy, zobrazení, vzorceGrafy, zobrazení, vzorce
Grafy, zobrazení, vzorce352
 

Similaire à KST/ICSHP - 3. a 4. přednáška (11)

Jan Čislinský: Seznámení se Sourcery aneb Základy metaprogramování ve Swiftu
Jan Čislinský: Seznámení se Sourcery aneb Základy metaprogramování ve SwiftuJan Čislinský: Seznámení se Sourcery aneb Základy metaprogramování ve Swiftu
Jan Čislinský: Seznámení se Sourcery aneb Základy metaprogramování ve Swiftu
 
Czjug Zari 2008
Czjug Zari 2008Czjug Zari 2008
Czjug Zari 2008
 
TPL - konkurenční, paralelní a asynchronní kód pro náročné
TPL - konkurenční, paralelní a asynchronní kód pro náročnéTPL - konkurenční, paralelní a asynchronní kód pro náročné
TPL - konkurenční, paralelní a asynchronní kód pro náročné
 
Tv 06
Tv 06Tv 06
Tv 06
 
.NET v SQL Serveru
.NET v SQL Serveru.NET v SQL Serveru
.NET v SQL Serveru
 
INPTP Rekapitulace
INPTP Rekapitulace INPTP Rekapitulace
INPTP Rekapitulace
 
Dependency injection v .Net Frameworku
Dependency injection v .Net FrameworkuDependency injection v .Net Frameworku
Dependency injection v .Net Frameworku
 
PR2021
PR2021PR2021
PR2021
 
Péhápkaři - Píšeme čitelný kód #4 by Petr Bechyně, Driveto
Péhápkaři - Píšeme čitelný kód #4 by Petr Bechyně, DrivetoPéhápkaři - Píšeme čitelný kód #4 by Petr Bechyně, Driveto
Péhápkaři - Píšeme čitelný kód #4 by Petr Bechyně, Driveto
 
Péhápkaři - Píšeme čitelný kód #2 by Petr Bechyně, Driveto
Péhápkaři - Píšeme čitelný kód #2 by Petr Bechyně, DrivetoPéhápkaři - Píšeme čitelný kód #2 by Petr Bechyně, Driveto
Péhápkaři - Píšeme čitelný kód #2 by Petr Bechyně, Driveto
 
Grafy, zobrazení, vzorce
Grafy, zobrazení, vzorceGrafy, zobrazení, vzorce
Grafy, zobrazení, vzorce
 

Plus de Jan Hřídel

Plus de Jan Hřídel (9)

C# - Vícevláknové aplikace
C# - Vícevláknové aplikaceC# - Vícevláknové aplikace
C# - Vícevláknové aplikace
 
ASP.NET MVC
ASP.NET MVCASP.NET MVC
ASP.NET MVC
 
INPTP wpf
INPTP   wpfINPTP   wpf
INPTP wpf
 
Aplikační nastavení v .NET
Aplikační nastavení v .NETAplikační nastavení v .NET
Aplikační nastavení v .NET
 
ADO.NET
ADO.NETADO.NET
ADO.NET
 
INPTP přednáška 01a 2016
INPTP přednáška 01a 2016INPTP přednáška 01a 2016
INPTP přednáška 01a 2016
 
Startup investor pitch
Startup investor pitchStartup investor pitch
Startup investor pitch
 
Nástěnka 01
Nástěnka 01Nástěnka 01
Nástěnka 01
 
Nástěnka 02
Nástěnka 02Nástěnka 02
Nástěnka 02
 

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

  • 1. Jazyk C# Přednáška 03/04 – příkazy, operátory, OOP – třídy, vlastnosti, události
  • 4. 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).
  • 5. 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
  • 6. 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.
  • 7. 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, …
  • 8. 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ů.
  • 9. 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.
  • 10. Příkazy – základní konstrukce • Deklarace  Plnohodnotný příkaz – může se objevit kdekoli mezi ostatními příkazy.
  • 11. 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.
  • 12. 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 :
  • 13. 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í.
  • 14. 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 "":
  • 15. 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
  • 16. 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.
  • 17. Cykly • do-while  Syntaxe  do příkaz while (podmínka) Platí totéž co pro podmínku příkazu if.
  • 18. 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
  • 19. 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.
  • 20. 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.
  • 21. 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.
  • 22. 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++
  • 23. 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.
  • 24. 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
  • 25. 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
  • 26. 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ů.
  • 27. 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(); }
  • 28. 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(); } }
  • 29. 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ů.
  • 30. 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.
  • 31. 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 */ } } }
  • 32. Příkaz yield • V C++ neexistuje • Používá se v iterátoru – viz dále.
  • 33. Příkaz try • Podobně jako v C++ se jedná o pokusný blok  Zachycení a ošetření výjimek – viz výjimky
  • 34. 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.
  • 35. Operátory a výrazy • Přehled operátorů  http://msdn.microsoft.com/en-us/library/6a71f45d.aspx
  • 36. 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í.
  • 37. 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
  • 38. 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)
  • 39. Čí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
  • 40. Čí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ů.
  • 41. Čí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.
  • 42. Čí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.
  • 43. 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)) { /* ... */ }
  • 44. 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.
  • 45. 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
  • 46. 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); }
  • 47. 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.
  • 48. 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.
  • 49. 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.
  • 50. 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
  • 51. 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
  • 52. 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
  • 53. 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
  • 54. Preprocesor • Podmíněný překlad  Nejjednodušší použití #define LADĚNÍ // ... #if LADĚNÍ Console.WriteLine("x = " + x); #endif
  • 55. 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
  • 56. 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.
  • 57. 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.
  • 58. 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.
  • 59. 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)
  • 60. 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
  • 61. 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.
  • 62. 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)
  • 63. 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
  • 64. 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í.
  • 65. 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
  • 66. 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é.
  • 67. 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
  • 68. 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.
  • 69. 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.
  • 70. 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.
  • 71. 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 } }
  • 72. 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 } }
  • 73. 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.
  • 74. 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.
  • 75. 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ů.
  • 76. 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.
  • 77. 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.
  • 78. TŘÍDY • Metody  Nestatické metody  Příklad class TridaA { int a; TridaA(int a) { this.a = a; } }
  • 79. 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.
  • 80. 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(); } }
  • 81. 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.
  • 82. 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.
  • 83. 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 } }
  • 84. 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.
  • 85. 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(); } }
  • 86. 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
  • 87. 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 } }
  • 88. 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.
  • 89. 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); } }
  • 90. • 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
  • 91. • 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
  • 92. • 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
  • 93. • 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 }
  • 94. • 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
  • 95. • 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
  • 96. • 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); } }
  • 97. • 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
  • 98. • 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
  • 99. • 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
  • 100. • 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(); } }
  • 101. • 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
  • 102. • 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
  • 103. • 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
  • 104. • 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 } }
  • 105. • 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
  • 106. • 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
  • 107. • Konstruktory  statický konstruktor  Nemá modifikátor přístupových práv  Neobsahuje parametry TŘÍDY
  • 108. • 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; } } // ... }
  • 109. • 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
  • 110. • 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
  • 111. • 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
  • 112. • 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
  • 113. • 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
  • 114. • 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
  • 115. • 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
  • 116. • 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(); } }
  • 117. • 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
  • 118. • 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
  • 119. • 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
  • 120. • 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
  • 121. • 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);
  • 122. • 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
  • 123. • 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
  • 124. • 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.ZmenaSou radnic); // 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(); } }
  • 125. • 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
  • 126. • 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
  • 127. • 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