Cvičenie 5
Na minulom cvičení sme robili kalkulačku. Táto však mala jeden veľký nedostatok: nedokázala upozorniť UI o dostupnosti výsledku. Dnes sa to zmení.
5.1 Call me back
Minulý týždeň sme mali možnosť vidieť niekoľko udalostí, ktoré sa vykonali pri stlačení tlačidla. Čo ale ak chceme, aby sa akcia vykonala bez nášho pričinenia, napríklad, keď sa zmení sledovaná hodnota.
Keďže máme mať oddelenú programovú logiku od UI, nemôžeme priamo z kalkulačky nastavovať hodnoty TextBoxu. Dokážeme však ale nejakým spôsobom odoslať referenciu na funkciu zodpovednú za aktualizovanie TextBoxu.
private EventHandler eventHandler; //predstavuje neparametrický event handler - chýba EventArgs
Ak použijeme typový parameter T, tak vieme dosiahnuť nasledovné:
private EventHandler<T> eventHandler; // default, do not use
//----------------------------------------------------------
private EventHandler<int> eventHandler = OnSomething;
private void OnSomething(object sender, int args)
{
//magic happens here
}
//other class, store the event handler as a variable
public void SetOnUpdateHandler(EventHandler<int> eventHandler)
{
this.eventHandler = eventHandler;
}
Typový parameter nám, narozdiel od pretypovania, zabezpečuje vykonanie kontroly pri kompilácií, takže nehrozí runtime exception ako pri nesprávnom pretypovaní a vďaka tomu, že sa nemusí riešiť (un)boxing je to aj rýchlejšie.
Na mieste tento event vieme vyvolať dvoma spôsobmi:
eventHandler.Invoke(sender, eventArgs); //variant 1
eventHandler(sender, eventArgs); //variant 2
eventHandler.Invoke(this, 5);
EventHandler môže byť využitý len triedou, ktorá ho definuje, ale vie referenciu naň odovzdať aj objektom iných tried, ktoré ho následne môžu zavolať nad objektom pôvodnej triedy.
5.2 Properties
Doteraz sme používali členské premenné, ku ktorým sme mali prístup pomocov gettera a settera. C# však ponúka aj iný, často vhodnejší prístup (tieto akcie sa vykonajú vždy pri prístupe ku premennej, narozdiel od gettera/settera ktorý musý byť volaný explicitne):
public int MyProperty {get; set;} //public getter & setter
public int MyProperty {get; private set;} //public getter, private setter
private int _myProperty;
public int MyProperty
{
get
{
//other magic may happen here
return _myProperty;
}
private set
{
_myProperty = value; //value is implicitly declared as the input value
//other magic may happen here
}
}
Upravte kalkulačku, aby pracovala s properties namiesto klasických členských premenných a na vhodnom mieste zabezpečte, aby bol o zmene hodnoty upozornený TextBox a aby sa aktualizoval:
- nech je v Calculator premenná ktorá uloži v sebe EventHandler s typovým parametrom string
- pridajte v Calculator public void SetOnUpdateHandler(EventHandler eventHandler)
- v MainForm vytvorte metódu so signatúrou zodpovedajúcou EventHandler-u v ktorej sa aktualizuje display kalkulačky
- v Calculator pri zmene hodnoty použite Invoke (príklad je vyššie)