Transcript vjezbe07

Računarski praktikum 3
Vježbe 07
Vinko Petričević
Iznimke. Delegati i
događaji
Iznimke




Dio programa u kojem očekujemo neku
anomaliju
Iznimka najčešće sadrži neku informaciju o
anomaliji
Kada je iznimka “bačena” stog se odmotava i
traži se handler koji će ju obraditi. Ako ju nitko
ne obradi, program se “ruši”
Iznimka može biti tipa System.Exception ili iz
nekog tipa izvedenog iz njeg (npr. u imenskom
prostoru System imamo ArgumentNullException,
InvalidCastException, OverflowException…)
Iznimke


Iznimku generiramo ključnom riječi throw, a
metoga za hvatanje iznimki počinje sa catch, koji
uvijek dolazi u paru sa try
Unutar try bloka navedemo kritičan dio kôda
(unutar kojeg bi se mogao desiti throw), a nakon
toga slijedi catch blok koji eventualnu iznimku
obrađuje
Generiranje iznimke
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Ulaz u Main...");
f1();
Console.WriteLine("Main izvršena.");
}
static void f1()
{
Console.WriteLine("Ulaz u f1...");
f2();
Console.WriteLine("f1 izvršena.");
}
static void f2()
{
Console.WriteLine("Ulaz u f2...");
throw new System.Exception(); // izbacujemo iznimku
Console.WriteLine("f2 izvršena.");
}
}
Hvatanje iznimke
...
static void f2()
{
Console.WriteLine("Ulaz u f2...");
try
{
Console.WriteLine("Ulaz u try blok...");
throw new System.Exception();
Console.WriteLine("Izlaz iz try bloka...");
}
catch
{
Console.WriteLine("Iznimka uhvaćena i obrađena.");
}
Console.WriteLine("Izlaz iz f2.");
}
Zadatak

Izmijenite prethodni primjer, tako da se iznimka
hvata u funkciji f1, te u main-u. Kometirajte što
se mijenja
Namjenske iznimke

Često imamo različiti kôd za obrađivanje
iznimaka različitog tipa. Osim takozvanog
generičkoh catch bloka, možemo navesti tip
iznimke koji on obrađuje (navodimo prvo
specijalni tip)
try
{
…
}
catch (System.DivideByZeroException) {
Console.WriteLine("Iznimka dijeljenja s nulom uhvaćena!");
}
catch (System.ArithmeticException) {
Console.WriteLine("Aritmetička iznimka uhvaćena!");
}
catch {
Console.WriteLine("Nepoznata iznimka uhvaćena!");
}
Finally

Ponekad želimo izvršiti dio koda bez obzira na to
da li se dogodila greška ili ne
try
{
…
}
catch {
…
}
finally {
Console.WriteLine(“Ovo se ce izvrsiti uvijek na kraju!");
}

Nakon eventualno obrađenih iznimaka, izvrši se
finally blok
Finally

Ponekad želimo izvršiti dio koda bez obzira na to
da li se dogodila greška ili ne
try
{
…
}
catch {
…
}
finally {
Console.WriteLine(“Ovo se ce izvrsiti uvijek na kraju!");
}

Nakon eventualno obrađenih iznimaka, izvrši se
finally blok
System.Exception objekt



Svojstvo Message je readonly, i postavlja se prilikom kreiranja
iznimke
Svojstvo HelpLink se može i mijenjati i služi da se omogući vezu do
help datoteke sustava pomoći
Svojstvo StackTrace se može samo čitati i njega automatski
postavlja .net framework
static double Podijeli(double a, double b) {
if (b == 0) {
DivideByZeroException e = new DivideByZeroException();
e.HelpLink = "http://www.math.hr"; // postavljamo HelpLink
throw e;
}
if (a == 0) {
// Message možemo postaviti jedino kroz konstruktor
throw new System.ArithmeticException("Nulu ne možete dijeliti!");
}
return a / b;
}
…
System.ApplicationException

Ako nam normalne iznimke nisu dobre, možemo samo napraviti
klasu (koja se najčešće izvodi iz ApplicationException), te u njoj
možda dodati dodatne informacije o pogrešci
InnerException

Ako nismo do kraja obradili iznimku, možemo ju proslijediti dalje na
obradu. U tom slučaju kreiramo iznimku, čije svojstvo
InnerException postavimo na trenutnu iznimku, te ponovo bacimo tu
novu iznimku
Delegati
[modifikator pristupa] delegate NazivDelegata(potpisMetode);
public delegate int KojiJePrvi(object o1, object o2);

nakon definiranja u njega možemo učahuriti
bilo koju metodu s istim popisom parametara
i povratnim tipom – slično kao pointeri na
funkcije u C-u
Primjer 1
public class Osoba {
public string ime, prezime;
}
public delegate int usporedi(Osoba o1, Osoba o2);
class Program
{
public static int usporediPoImenu(Osoba o1, Osoba o2)
{
return o1.ime.CompareTo(o2.ime);
}
public static int usporediPoPrezimenu(Osoba o1, Osoba o2)
{
return o1.prezime.CompareTo(o2.prezime);
}
static void Main(string[] args)
{
usporedi u = new usporedi(usporediPoImenu);
Osoba o1, o2;
...
if (u(o1, o2) > 0) { ... }
}
}
Višeodredišni delegati

delegate možemo dodavati i oduzimati pomoću operatora + i –
(odnosno += i -=), te će se onda osim jedne, izvršiti sve funkcije koje
su dodane
Primjer 2
class KlasaSDelegatom {
// deklaracija delegata
public delegate void StringDelegat(string s);
}
class ImplementirajucaKlasa {
public static void ZapisiString(string s) {
Console.WriteLine("Zapisivanje niza znakova: {0}", s);
}
public static void ZabiljeziString(string s)
{
Console.WriteLine("Bilježenje niza znakova: {0}", s);
}
public static void PosaljiString(string s) {
Console.WriteLine("Odašiljanje niza znakova: {0}", s);
}
}
Primjer 2
class Program {
static void Main(string[] args) {
// definiramo tri delegata tipa StringDelegat
KlasaSDelegatom.StringDelegat Zapisivac, Biljeznik, Odasiljac;
// definiramo još jednog delegata tipa StringDelegat
KlasaSDelegatom.StringDelegat ViseodredisniDelegat;
// instanciramo tri delegata
Zapisivac = new KlasaSDelegatom.StringDelegat(
ImplementirajucaKlasa.ZapisiString);
Biljeznik = new KlasaSDelegatom.StringDelegat(
ImplementirajucaKlasa.ZabiljeziString);
Odasiljac = new KlasaSDelegatom.StringDelegat(
ImplementirajucaKlasa.PosaljiString);
// pozivamo metodu delegata Zapisivac
Zapisivac("Niz znakova prosljeđen Zapisivaču");
// pozivamo metodu delegata Biljeznik
Biljeznik("Niz znakova prosljeđen Bilježniku");
// pozivamo metodu delegata Odasiljac
Odasiljac("Niz znakova prosljeđen Odašiljaču");
Primjer 2
Console.WriteLine("Viseodredisnidelegat = Zapisivac + Biljeznik");
// kombiniramo dva delegata u ViseodredisniDelegat
ViseodredisniDelegat = Zapisivac + Biljeznik;
// pozivamo 2 metode ViseodredisniDelegat-a
ViseodredisniDelegat("Prvi prosljeđeni niz znakova ");
Console.WriteLine("Viseodredisnidelegat += Odasiljac");
// dodajemo i treći delegat u ViseodredisniDelegat
ViseodredisniDelegat += Odasiljac;
// pozivamo 3 metode ViseodredisniDelegat-a
ViseodredisniDelegat("Drugi prosljeđeni niz znakova");
Console.WriteLine("Viseodredisnidelegat -= Biljeznik");
// oduzimamo Biljeznika iz ViseodredisniDelegat
ViseodredisniDelegat -= Biljeznik;
// pozivamo 2 preostale metode ViseodredisniDelegat-a
ViseodredisniDelegat("Treći prosljeđeni niz znakova");
}
}
Anonimne metode

Da bi skratili pisanje kôda, delegate možemo
koristiti za kreiranje anonimnih metoda
delegate int binOp(int x, int y);
static void Main(string[] args)
{
binOp usp = delegate(int x, int y)
{
return x-y;
};
}

U vs2008 imamo lambda operator koji još
pojednostavljuje kreiranje anonimnih metoda
Delegati i asinhrono pozivanje


Osim sinhronog pozivanja funkcija, delegati nam omogućuju i
asinhrono pozivanje (što je objašenjno na kolegiju Distribuirani
procesi - BeginInvoke) – kreira se novi thread koji izvršava metodu,
a naš program nastavlja sa radom.
Rezultate asinhronog poziva možemo provjeriti sa EndInvoke
Događaji




Programi u grafičkim sučeljima moraju biti u
stanji odgovarati na događaje
Događaj može biti pritisak na gumb, odabir
opcije iz izbornika, događaj vremena i slično
U grafičkim sučeljima bilo koji objekt može
pokrenuti događaj, a neki drugi objekt može biti
zainterasiran za taj događaj. Tko će obraditi
događaj nije bitno onome tko ga je pokrenuo
Kad neki objekt objavi događaj, svi objekti koji su
pretplaćeni na taj događaj bivaju o tome
obaviješteni
Događaji



U C# događaji se implementiraju pomoću
delegata. Višeodredišni delegati nam omogućuju
da se više objakata pretplati na neki događaj
Klasa izdavač definira delegat, a pretplatnička
klasa koja se želi pretplatiti funkciju koja učahuri
metodu koja će obrađivati događaj (event
handler)
Prije kreiranja događaja, izdavač treba provjeriti
je li itko prijavljan na događaj, jer ćemo u
protivnom dobiti grešku
Događaji


Umjesto +=, za dodavanje novog preplatnika,
mogli smo koristiti =, te bi prethodni pretplatnik
mogao biti onda isključen, a delegat bi mogli
pozvati i izravno
Zbog toga je ubačena ključna riječ event
public event RukovateljPromjenomSekunde NaPromjenuSekunde;

Sada događaj može pokrenuti samo klasa koja
ga je kreirala, te na njemu rade samo operatori
+= i -=