Pojam | Značenje |
---|---|
Delegat | Tip koji opisuje potpis funkcije |
Anonimna funkcija | Funkcija koja nema ime |
Lambda izraz | Izraz kojim se kreira anonimna funkcija |
Predikat | Funkcija koja prima jedan parametar i vraća bool (TODO: Izbaciti ukoliko se prebacuje u naredni termin) |
Događaj | TODO |
Delegat je tip koji opisuje potpis funkcije.
Anonimna funkcija nema ime, kreira se samo navođenjem potpisa i tela sa implementacijom.
Naravno, da bi se takva funkcija koristila, moramo sačuvati referencu na nju, i pozivati je preko te reference.
Anonimna funkcija se može kreirati na više načina. U nastavku ćemo proći kroz dva: Delegat sintaksa i Lambda izraz.
delegate (parametri) { naredbe }
Parametri moraju imati naveden tip.
Delegat (tip funkcije) BinaryOp
je definisan kao:
delegate int BinaryOp(int a, int b);
Anonimnu funkciju ćemo kreirati na sledeći način:
BinaryOp add = delegate (int x, int y) {
return x + y;
};
Izraz koji kreira novu anonimnu funkciju i vraća referencu na nju.
(parametri) => izraz
(parametri) => { naredbe }
Parametri ne moraju imati naveden tip.
Koristićemo delegat BinaryOp
iz primera delegat sintakse.
Anonimnu funkciju ćemo kreirati na sledeći način
BinaryOp add = (x, y) => x + y;
Umesto izraza možemo napisati blok sa naredbama:
BinaryOp add = (x, y) => {
return x + y;
};
U prethodnim primerima smo kreirali anonimnu funkciju koja sabira dva broja. Referencu na tu funkciju smo čuvali u promenljivoj add
.
Sada, funkciju možemo pozivati preko te promenljive:
int result = add(17, 33);
Događaj, tj. event, je specijalni član klase ili objekta, koji se ponaša kao referenca na funkciju određenog tipa (delegata), a u pozadini zapravo čuva nekakvu listu referenci na funkcije tog tipa, i na poziv event-a (kao što bi se pozvala obična funkcija) pozivaju se redom sve funkcije čije su reference tu sačuvane.
Pre nego što se referenca na naku funkciju doda u event, odnosno pre nego što se ona prijavi/pretplati (subscribe) na event, event će biti null
.
Prvo ćemo definisati tip event-a, odnosno tip funkcija koje će event čuvati:
public delegate void TempChangeHandler(double temp);
Zatim, kreiraćemo klasu čija će instanca predstavljati termometar koji simulira merenje temperature:
class Termometer
{
double current = 20;
public event TempChangeHandler TempChange;
public void Start()
{
Random rnd = new Random();
while (true)
{
Thread.Sleep(1000); // Čekanje, 1000 milisekundi
int change = rnd.Next(3) - 1; // Moguće vrednosti: -1, 0, 1
current += change; // Temperatura će se smanjiti, povećati ili ostati ista
if (change != 0) // Ukoliko je došlo do promene ...
TempChange?.Invoke(current); // ... i ukoliko TempChange nije null, pozivaju se sve prijavljene funkcije
}
}
}
U klasi Termometer
smo definisali event koji se zove TempChange
, a koji je tipa TempChangeHandler
. U metodi Start
se nalazi logika koja simulira merenje, i tu je, realizovano i pozivanje, tj. aktiviranje tog event-a.
Kada nema prijavljenih metoda event TempChange
će biti null
. Ukoliko tada aktiviramo event dobićemo grešku NullReferenceException
. Zato moramo proveriti da li je on null
, i aktivirati ga samo ukoliko nije. Možemo koristiti ?.
operator, koji evaluira ceo poziv u null
ukoliko je TempChange
null
i tada ne radi poziv metode Invoke
, a u suprotnom regularno poziva Invoke
. Drugi način za ovu proveru bi bio:
if (change != 0 && TempChange != null)
TempChange(current); // ili TempChange.Invoke(current)
Takođe, kreiraćemo klasu sa metodom koja ispisuje temperaturu:
class TempLogger
{
public void Log(double temp)
{
Console.WriteLine("[Logger] " + temp);
}
}
Sada ćemo prijaviti više različitih tipova funkcija na event TempChange
:
static class Program
{
static void LogTemp(double temp)
{
Console.WriteLine("[Static] " + temp);
}
public static void Main(string[] args)
{
var sensor = new Termometer();
var logger = new TempLogger();
sensor.TempChange += LogTemp; // Statička metoda (nema "this")
sensor.TempChange += logger.Log; // Metoda uvezana sa objektom (ima "this")
sensor.TempChange += t => Console.WriteLine("[Anonim] " + t); // Anonimna funkcija
sensor.Start();
}
}
Prijavljivanje funkcije na event se vrši pomoću operatora +=
. Odjavljivanje se analogno tome vrši preko operatora -=
, samo kao desni operand navedemo referencu na funkciju koju smo prethodno prijavili, i onda će biti odjavljena.
Svaki put kada se temperatura promeni u konzoli se ispisuje:
[Static] broj
[Logger] broj
[Anonim] broj
«< 2. Termin | 4. Termin »> |