Poznáváme C# a Microsoft.NET 16. díl – události

Po delegátech se budu v tomto díle věnovat další velmi zajímavé vlastnosti .NET frameworku, která se často používá při zpracovávání asynchronních operací v tomto prostředí. K tomu nám v .NET frameworku a tím pádem i v jazyku C# slouží členy třídy zvané události.

Co jsou události?

Události představují v jazyku C# cestu, která umožňuje třídě upozornit jinou třídu nebo třídy, že v ní došlo k něčemu zajímavému, na což by mohla tato třída respektive třídy určitým způsobem zareagovat. Časté použití můžeme nalézt v implementaci grafických uživatelských prostředí pro upozornění, že uživatel provedl nějakou akci, na níž by mohla být implementována reakce. Samozřejmě to není jediné možné použití události. Události se hodí všude tam, kde je potřeba upozornit okolí na to, že se v objektu respektive třídě došlo k nějaké změně stavu. Pro definici metod, které mohou být použity pro reakci na vzniklou událost slouží delegáty, kterými jsem se zaobíral v minulém díle, a proto by bylo vhodné abyste měli v implementaci delegátů jasno.

Deklarace události

Pro deklaraci nové události ve třídě použijeme klíčové slovo event. Musíme také určit typ delegáta, který asociujeme s touto události. To má za následek to, že třídy, které budou chtít na vzniklou událost reagovat, musí delegáta tohoto typu vytvořit a k tomuto delegátu asociovat obslužnou metodu(y).

modifikátory event typ_delegáta identifikátor_události;

Vyvolání události

Tím, že jsme ve třídě deklarovali událost, je možné k ní přistupovat jako ke členu delegáta určeného typu. Pokud tento člen nabývá hodnoty null, znamená to, že žádná jiná třída si tuto událost takzvaně nepředplatila, jinými slovy, že nehodlá na nově vzniklou událost jakýmkoli způsobem reagovat. Proto je vhodné před vyvoláním události vždy zkontrolovat jestli člen události nenabývá hodnoty null. Jelikož se tedy událost vyvolá stejně jako volání delegáta obecný způsob vyvolání vypadá takto:

if (identifikátor_události != null)
identifikátor_události (seznam_případných_parametrů);

Ukázková třída vyvolávající událost

Po lehkém obecném úvodu bych rád demonstroval použití události na konkrétním případu. Na ukázku definujeme třídu Žárovka, která bude, na rozdíl od její v implementace v jednom s prvních dílů tohoto seriálu, při svém rozsvícení či zhasnutí vyvolávat událost oznamující změnu stavu.

//deklarace delagata, ktery bude slouzit jako predpis metody
//predstavujici reakci na udalost (handler)
public delegate void ZmenaStavuHandler();

/// <summary>
/// Trida predstavujici zarovku, ktera vyvolava udalost
/// </summary>
public class Zarovka
{
 private int vykon;
 private bool sviti;

 //deklarace udalosti
 public event ZmenaStavuHandler Zmeneno;
  
 public int Vykon
 {
  get
  {
   return vykon;
  }
  set
  {
   vykon = value;
  }
 }

 public bool Sviti
 {
  get
  {
   return sviti;
  }
 }

 public Zarovka(int vykon)
 {
  this.vykon = vykon; 
 }

 //tato metoda vyvolava udalost
 protected void PriZmene()
 {
  //kontrola, zda existuji klientske objekty
  //ktere si udalost predplatitili
  if (Zmeneno != null)
   //vyvolani udalosti
   Zmeneno();
 }
 
 public void Rozsvitit()
 {
  sviti = true;
  //zavolani metody, ktera vyvolava udalost
  PriZmene();
 }

 public void Zhasnout()
 {
  sviti = false;
  //zavolani metody, ktera vyvolava udalost
  PriZmene();
 }
}

Na úrovni jmenného prostoru je deklarován delegát ZmenaStavuHandler, který je použit pro určení typu delegáta události Zmeneno ve třídě Žárovka. Delegát předepisuje, že obslužná metoda nebude vracet hodnotu a bude bez vstupních parametrů. Za zmínku stojí metoda PriZmene, která je určena k vyvolání události Zmeneno. Metoda zkontroluje jestli existuje nějaký klientský objekt, který si předplatil událost a pokud ano, dojde k vyvolání události. Metoda PriZmene je volána metodami Rozsviti a Zhasnout, které mění hodnotu soukromého atributu sviti.

Obsluha událostí

Pokud chceme nastalou událost nějaké instance třídy obsloužit, musíme nějakou třídu učinit takzvaným předplatitelem události. Zvenčí, lze k události třídy nebo její instance přistoupit jako ke členu, ale použití tohoto členu je velmi omezené. Jediné co je .NET frameworkem dovoleno s členy typu událost provést je přidání instance delegáta do seznamu delegátů pro její obsluhu nebo naopak instancí delegáta z tohoto seznamu vyjmout. K přidání instance delegáta slouží operátor += a k jeho vyjmutí operátor -= . Následující kód třídy ZarovkaTest ukazuje způsob obsluhy událostí ve třídě:

public class ZarovkaTest
{
 public static void Test()
 {
  //vytvoreni instance tridy Zarovka
  Zarovka mojeZarovka = new Zarovka(100);
  //vytvoreni instanci delegatu pro obsluhu
  //a jejich nasledne prirazeni do seznamu
  //instanci delegatu pro obsluhu udalosti
  mojeZarovka.Zmeneno += new ZmenaStavuHandler(StavZarovkyZmenenObsluha);
  mojeZarovka.Zmeneno += new ZmenaStavuHandler(StavZarovkyZmenenObsluha2);
  //metoda zapricini vyvolani udalosti
  mojeZarovka.Rozsvitit();
 }
 private static void StavZarovkyZmenenObsluha()
 {
  Console.WriteLine("Stav zarovky byl zmenen");
 }

 private static void StavZarovkyZmenenObsluha2()
 {
  Console.WriteLine("Druha metoda obsluhujici nastalou zmenu stavu zarovky");
 }
}

Jediné co se v metodě Test této třídy děje, je vytvoření instance třídy žárovka, následné vytvoření instancí delegátů typu ZmenaStavuHandler, které jsou asociovány s obslužnými metodami a ihned připojeny k obsluze události. Potom dochází k volání metody Rozsvit, která zapříčiní vyvolání události. Výstup po zavolání této metody bude tedy vypadat následovně, jak jistě mnozí předpokládají.

Stav zarovky byl zmenen
Druha metoda obsluhujici nastalou zmenu stavu zarovky

Události a dědičnost

Jednou ze specifických vlastností událostí, je že nemohou být přímo vyvolány z žádné jiné třídy, než ve které byly deklarovány, to znamená ani ve třídách odvozených, takže v případě, že bychom se pokusili zkompilovat následující kód, nebyli bychom úspěšní.

public class BarevnaZarovka : Zarovka
{
 public BarevnaZarovka(int vykon) : base(vykon){ }

 public BarevnaZarovka(int vykon,System.Drawing.Color barva) : base(vykon)
 {
  this.barva = barva;
 }
     
 private System.Drawing.Color barva;
 public System.Drawing.Color Barva
{
 get
  {
   return barva;
  } 
  set
  {
   //chyba - udalost neni mozne v teto
   //tride udalost vyvolat
   Zmeneno();
   barva = value;
  }
 }
}

Vytvořil jsem třídu reprezentující barevnou žárovku, která je odvozena od třídy Zarovka. Nicméně pokud se v ní pokusím vyvolat událost Zmeneno, překlad programu díky tomu skončí chybou. Řešení v těchto situacích se naskýtá ve formě zavolání metody implementované na bázové třídě, která danou událost vyvolá. Pochopitelně tato metoda musí mít takový specifikátor přístupu, aby k ni bylo možné v odvozené třídě přistoupit. V našem případě se jedná o metodu PriZmene. Takže funkční řešení by vypadalo takto:

public class BarevnaZarovka : Zarovka
{
 public BarevnaZarovka(int vykon) : base(vykon){ }
  public BarevnaZarovka(int vykon,System.Drawing.Color barva) : base(vykon)
 {
  this.barva = barva;
 }
     
 private System.Drawing.Color barva;

 public System.Drawing.Color Barva
 {
  get
  {
   return barva;
  }
  set
  {
   PriZmene();
   barva = value;
  }
 }
}

Tím, že metodu vyvolávající událost zpřístupníme odvozeným třídam, tedy dosáhneme toho, že odvozené třídy budou pomocí této metody schopny danou událost vyvolat. Odvozeným třídám můžeme nechat i vetší volnost při vyvolávání události a to tím, že metodu vyvolávající událost definujeme jako virtuální a tím pádem budou odvozené třídy tuto metodu překrýt a naimplementovat po svém.

Zdrojové kódy k příkladům naleznete zde.

V příštím díle si ještě prohloubíme znalosti o používání událostí v .NET frameworku.

Diskuze (11) Další článek: Kabelový internet chello má 50 tisíc uživatelů

Témata článku: Microsoft, Software, Programování, Private, Časté použití, Barevná žárovka, Event, Public, Strong, Události, Microsoft NET, Zavolání, Obecný způsob, Jediný způsob, Žárovka, Díl, Software na Heureka.cz



Sex manželských párů? Jen výjimečně. Ložnice ovládnou roboti s umělou inteligencí

Sex manželských párů? Jen výjimečně. Ložnice ovládnou roboti s umělou inteligencí

** Sex manželských párů jen při zvláštních příležitostech. ** Ložnice ovládnou sexuální roboti s umělou inteligencí. ** I to je jeden ze závěrů Mezinárodní robotické konference.

Filip KůželJiří Liebreich
RobotiSexUmělá inteligence
Druhotné softwarové licence. Kdo by nechtěl legální Windows za stovku…

Druhotné softwarové licence. Kdo by nechtěl legální Windows za stovku…

Koupě originálního programového vybavení přímo od výrobce není jedinou možností, jak sehnat pro váš počítač legální software. Další možností je koupit licenci od toho, kdo ji už nepotřebuje nebo nevyužije. Můžete ušetřit nemalou částku, zároveň si však dávejte pozor na podvodníky.

Jan Spěšný
Placené aplikace zadarmo. Huawei AppGallery se může brzy stát cílem hromadného stahování aplikací

Placené aplikace zadarmo. Huawei AppGallery se může brzy stát cílem hromadného stahování aplikací

** Vývojář upozornil Huawei na kritikou chybu API v AppGallery ** Kdokoliv si nyní může stáhnout placené aplikace zdarma ** Pokud nemají vlastní ochrany, půjdou normálně používat

Martin Chroust
Huawei AppGalleryZdarmaChyba
Designéři zkombinovali iPhone s populární herní konzolí. Takový telefon by se líbil každému hráči

Designéři zkombinovali iPhone s populární herní konzolí. Takový telefon by se líbil každému hráči

** Takto by vypadal iPhone 14 zkřížený s herní konzolí ** Má tři displeje, joysticky i herní tlačítka ** Nechyběla by špičková výbava i chlazení.

Martin Miksa
CaviarHerní mobilyiPhone
Nový hit. Tahle appka vám udělá profilovku jako od pouličního ilustrátora

Nový hit. Tahle appka vám udělá profilovku jako od pouličního ilustrátora

** Aplikace NewProfilePic se na Androidu stala hitem ** Můžete si v ní vytvořit profesionálně vypadající profilovky ** Pozor ale na agresivní cenovou politiku za Pro verzi

Martin Chroust
FotografieUmělá inteligenceMobilní aplikace
25 nejlepších filmových parodií, které můžete vidět. Víme, kde je najdete online

25 nejlepších filmových parodií, které můžete vidět. Víme, kde je najdete online

Filmové parodie jsou divácky velmi vděčné a mezi filmaři oblíbené. Tvůrci v nich mohou totiž zcela beztrestně vykrádat cizí díla a v jejich nápodobě popustit uzdu své fantazii. Vybrali jsme nejlepší zahraniční i české parodie.

Marek Čech
Filmy, které musíte vidět
Nandali jste to Putinovi? Rusko zveřejnilo IP adresy, které se zapojily do obřího DDoS. Možná je tam i ta vaše

Nandali jste to Putinovi? Rusko zveřejnilo IP adresy, které se zapojily do obřího DDoS. Možná je tam i ta vaše

** Zapojte se do útoků, lákají lidé na Twitteru ** Mnohé weby Moskvy skutečně nejedou ani v Rusku ** Pozor na podvodníky, toto je příležitost pro phishing

Jakub Čížek
KyberválkaRusko
Ruský notebook je přesně tak hrozný, jak si představujete

Ruský notebook je přesně tak hrozný, jak si představujete

** Letos se začne prodávat první ruský notebook Bitblaze Titan ** Neohromí výkonem ani výbavou, nýbrž svou neotesaností ** A stejně nakonec není tak ruský, jak se tváří

Lukáš Václavík
RuskoNotebooky
Světu hrozí „vlhká žárovka.“ Měla dorazit až v polovině století, ale už je tu

Světu hrozí „vlhká žárovka.“ Měla dorazit až v polovině století, ale už je tu

** Nejteplejší místo na Zemi nemusí být to nejnebezpečnější ** Největším zabijákem se stane až mix tepla a vlhkosti ** Asie se nebezpečně přiblížila hraniční hodnotě 35 °C twb

Jakub Čížek
MeteorologieGlobální oteplování