Delegates
Klicove slovo delegate, vzdy to je referencni typ, co ktery odpovida hlavicce metode. Musime specifikovat navratovy typ a parametry.
delegate int MathDelegate(int a, int b);
class A {
public int Add(int a, int b) => a + b;
}
class Math {
public static int PerformOperation(int a, int b, MathDelegate operation) => operation(a, b);
}
A a = new A();
MathDelegate add = new(a.Add);
int result = Math.PerformOperation(1, 2, add);
Dedicnost: deleates : System.MulticastDelegate : System.Delegate : System.Object
Syntaxe
MathDelegate add = new(a.Add)vyrobi noveho delegataMathDelegate add = a.Addje skoro to same, ale saha do cache, takze se novy delegat nevytvori. Vetsinou chci pouzit tohle, leda bych ty delegaty pouzival treba jako klice do slovniku.operation(a,b)je zkratka zaoperation.Invoke(a,b)- TOHLE NENI REFLECTION INVOKE
MethodInfo.Invoke - pri reflection prekladac nevi, co dostane za paramerty a musi se delat runtime check
- tady to je silne typovane, takze se to normalne prelozi do CIL kodu
- TOHLE NENI REFLECTION INVOKE
- instance delegatu je immutable, podobne jako stringy
- Ruzni delegati co maji stejny signature se do sebe NEDAJI prirazovat, nijak od sebe totiz nededi.
Jak to funguje?
- delegat si pamatuje nejaky pointer na metodu
- pokud je to instancni metoda, tak i nejaky
object this, aby se to mohlo zavolat - pokud to je staticka metoda, tak
thisjenull - tim, ze je delegat immutable, tak to konkretni
thisje tam navzdy, takze ruzne instancni metody se muzou chovat jinak - pokud je
thisstruktura, tak se boxuje
Existuji i genericti delegati, existuje tam covariance a contravariance.
Delegati a viditelnost
delegate void Process(int a);
class A {
private void privateMethod(int a);
public Process UsefulMethod() => privateMethod;
}
Umoznuje to zvenci dostat pristup k nejake private metode. Ale muzu tu private metodu bezpecne smazat, naimplementovat to uplne jinak a v pristi verzi jen vracet delegata na jinou metodu. Zvenci se nic nezmeni.
Preddefinovani delegati
delegate void Action<...>(...); // muze mit rouzne parametry, ale vraci void
delegate TResult Func<...,TResult>(...); // opet ruzne parametry, posledni TResult je navratovy typ
delegate bool Predicate<T>(T item); // vraci bool, bere jeden parametr
Kdyz udelam var d = <nejaka metoda>, tak se to prelozi a vybere se nejaky preddefinovany delegat.
Efektivita delegatu
Vyroba delegata neco stoji, volani vyjde prakticky nastejno.
Delegati maji vlastnost .Method, ktera vraci MethodInfo, pouziva se to pro reflection a je to docela drahe. Ale cachuje se to.
Podobne na instanci MethodInfo existuje genericka metoda
TD MethodInfo.CreateDelegate<TD>() where TD : Delegate
Takze kdyz mam MethodInfo a chci tu metodu casto volat, tak vyrobim delegata a misto MethodInfo.Invoke volam delegat.Invoke, coz je mnohem rychlejsi.