Natrag   Forum.hr > Informatička tehnologija > Za napredne korisnike > Programiranje

Programiranje Za programere i one koji to žele postati ...

Odgovor
 
Tematski alati Opcije prikaza
Old 24.08.2003., 23:49   #1
Programiranje u .NET-u i C#-u: moja redovna "kolumna" :-)

Ovim postom zapocinjem moju redovitu forumsku "kolumnu" u kojoj cu se baviti programiranjem u C#-u i .NET-u. Za citanje kolumne potrebno je solidno poznavanje objektno-orijentiranog programiranja npr. u C++-u ili Javi. U svojim tekstovima nastojat cu obuhvatiti one stvari koje su specificne za C# i .NET, i koje se ne pojavljuju (ili su nesto drugacije) u ostalim OO jezicima.
Danasnja tema bit ce delegati:

Callback funkcije spadaju u vrlo korisne programske konstrukte. Sjetimo se npr. standardne C-funkcije qsort. Ova funkcija kao jedan od ulaznih parametara prima pointer na funkciju kojom usporedjujemo elemente polja kojeg sortiramo. To je vrlo korisna mogucnost, jer time rad funkcije qsort poopcavamo, tako da ona ispravno radi ne samo sa standardnim tipovima podataka (poput int, float...), nego je mozemo prilagoditi nasim potrebama i sortirati neki korisnicki-definiran tip podataka po kriteriju kojeg sami odaberemo.

I u Windows-programiranju cesta je upotreba callback funkcija: koriste se za windows-procedure, za razne hook-ove, za asinkrono pozivanje funkcija, itd.

Callback funkcije koriste se, naravno i u Microsoft .NET-u, i to za vrlo razlicite stvari: npr. mozemo registrirati callback metodu koja ce se pozvati onda kad se neki assembly ucita, kada se promijeni stanje nekog prozora, kad se izabere neka opcija u meniju, kada s radom zavrsi neka asinkrona operacija, itd, itd.

Adresa neke funkcije u C-u i u C++-u je samo broj (tj. adresa memorijske lokacije prvog bajta asemblerkog koda te funkcije). Ta adresa u sebi ne nosi nikakve druge podatke kao npr. broj parametara koji funkcija prima, tipove tih ulaznih parametara ili tip kojeg funkcija vraca kao rezultat svog rada. Ukratko, C/C++ callback funkcije nisu type-safe.

U .NET frameworku je drugacije: umjesto obicne adrese callback funkcije, koristimo type-safe mehanizam koji zovemo delegati. Sljedeci program daje nam jedan primjer koristenja delegata:

Kod:
using System;
using System.Windows.Forms;
using System.IO;

class Skup
{
   private Object[] elementi;

   public Skup(int brElem)
   {
      elementi = new Object[brElem];
      for (int i = 0; i < brElem; i++)
         elementi[i] = i;
   }

   // Definiramo tip CallBackFn 
   // (UOCI: ovaj tip je ugnjezden unutar klase Skup)
   public delegate void CallBackFn(Object value, int el, int brElem);


   public void ProsetajPoPoljuIZoviFunkciju(CallBackFn fn)
   {
      for (int el = 0; el < elementi.Length; el++)
      {
         if (fn != null)
         {
            // ako je zadana bar jedna callback funkcija, pozovi je
            fn(elementi[el], el + 1, elementi.Length);
         }
      }
   }
}


class TestDriver
{
   static void Main()
   {
      StatickiCallBackovi();
      CallBackoviInstance();
   }


   static void StatickiCallBackovi()
   {
      // Kreiraj skup od 5 elemenata
      Skup skupElemenata = new Skup(5);

      // Prosetaj po elementima skupa bez ikakve callback funkcije
      skupElemenata.ProsetajPoPoljuIZoviFunkciju(null);
      Console.WriteLine();

      // Prosetaj po elementima skupa i nad svakim elementom pozovi funkciju NaKonzolu
      skupElemenata.ProsetajPoPoljuIZoviFunkciju(
new Skup.CallBackFn(TestDriver.IspisNaKonzolu));
      Console.WriteLine();

      // Prosetaj po elementima skupa i nad svakim elementom pozovi funkciju UProzor
      skupElemenata.ProsetajPoPoljuIZoviFunkciju(
new Skup.CallBackFn(TestDriver.IspisUProzor));
      Console.WriteLine();

      // Prosetaj po elementima skupa i nad svakim elementom 
      // pozovi i funkciju NaKonzolu i funkciju UProzor
      Skup.CallBackFn cb = null;
      cb += new Skup.CallBackFn(App.IspisNaKonzolu);
      cb += new Skup.CallBackFn(App.IspisUProzor);
      skupElemenata.ProsetajPoPoljuIZoviFunkciju(cb);
      Console.WriteLine();
   }

   static void IspisNaKonzolu(Object value, int el, int brElem)
   {
      Console.WriteLine("Vrijednost elementa {0} od {1}: {2}.", el, brElem, value);
   }

   static void IspisUProzor(Object value, int el, int brElem)
   {
      MessageBox.Show(String.Format("Vrijednost elementa {0} od {1}: {2}.",
 el, brElem, value));
   }


   static void CallBackoviInstance()
   {
      // Kreiraj skup od 5 elemenata
      Skup skupElemenata = new Skup(5);

      // Prosetaj po elementima skupa i nad svakim elementom pozovi IspisUFile
      TestDriver testObj = new TestDriver();
      skupElemenata.ProsetajPoPoljuIZoviFunkciju(
new Skup.CallBackFn(testObj.IspisUFile));
      Console.WriteLine();
   }

   void IspisUFile(Object value, int el, int brElem)
   {

      StreamWriter sw = new StreamWriter("Datoteka.dat", true);
      sw.WriteLine("Vrijednost elementa {0} od {1}: {2}.", el, brElem, value);
      sw.Close();
   }
}
Uocimo klasu Skup na vrhu gornjeg programa. Zamislimo da klasa Skup sadrzi skup elemenata koje zelimo procesuirati jedan po jedan. Kada kreiramo objekt tipa Skup, njegovom konstruktoru proslijedjujemo broj elemenata od kojih se skup sastoji. Konstruktor tada kreira polje Objekata i inicijalizira da svaki objekt bude jedan cijeli broj.

Klasa Skup takodjer definira i tzv. delegat. Delegatom zadajemo signaturu callback metode. U nasem primjeru, delegat CallBackFn zadaje signaturu callback metode koja prima tri parametra (jedan Object, i dva int-a) i vraca vrijednost void. Na neki nacin, delegati su vrlo slicni typedef-ovima u C-u koji reprezentiraju adresu neke funkcije.
U nastavku, u klasi Skup definirali smo jos i funkciju ProsetajPoPoljuIZoviFunkciju. Ova metoda prima jedan ulazni parametar, fn, koji je ustvari referenca na CallBackFn delegat-objekt. ProsetajPoPoljuIZoviFunkciju "sece" po svim elementima polja i nad svakim elementom poziva metodu zadanu u varijabli fn. Toj metodi proslijedjuje se vrijednost elementa kojeg upravo procesiramo, redni broj tog elementa i ukupan broj elemenata u polju. Poanta je u tome da callback metoda moze procesirati elemente na koji god nacin zeli!

Metoda StatickiCallBackovi demonstrira razlicite nacine uporabe callback delegata. Najprije se konstruira objekt tipa Skup od 5 elemenata. Zatim se poziva ProsetajPoPoljuIZoviFunkciju sa ulaznim parametrom null. Ovo je prvi primjer upotrebe delegata. Prisjetimo se: ProsetajPoPoljuIZoviFunkciju je metoda koja nad svakim elementom u Skupu izvodi neku akciju. No, kako je CallBackFn parametar koji smo proslijedili ovoj funkciji bio null, svaki element ce se procesuirati bez pozivanja bilo kakve callback metode.

Iduca dva slucaja su ocita: prvi ce ispisati elemente skupa na konzolu, a drugi u MessageBox prozore, jer smo prvi put pozvali metodu ProsetajPoPoljuIZoviFunkciju s ulaznim parametrom TestDriver.IspisNaKonzolu, a drugi put s parametrom TestDriver.IspisUProzor. Primjetimo da smo upotrijebili kljucnu rijec new (npr. new Skup.CallBackFn(TestDriver.IspisNaKonzolu) ). Time smo u biti kreirali delegat koji u biti predstavlja tzv. tape-safe "wrapper" za funkciju IspisNaKonzolu.

Posljednja dva primjera pokazuju kako se delegati mogu medjusobno povezati u svojevrsni lanac. Najprije smo kreirali reference-varijablu cb na CallBackFn delegat objekt i inicijalizirali je na vrijednost null. Ta varijabla u biti pokazuje na zaglavlje vezane liste delegata. Vrijednost null naznacuje da u toj vezanoj listi zasad nemamo nijedan cvor. U nastavku programa konstruira se delegat-objekt koji predstavlja type-safe "wrapper" za TestDriver-ovu metodu IspisNaKonzolu. Nadalje, koristimo operator += , cime u vezanu listu delegata na koju pokazuje varijabla cb dodajemo netom konstruirani delegat. Nakon toga, ponovo pomocu operatora += u istu vezanu listu dodajemo jos jedan delegat, koji je, ovog puta, "wrapper" za metodu IspisUProzor.

Sada, kada se pozove funkcija ProsetajPoPoljuIZoviFunkciju sa ulaznim parametrom cb (koji je, podsjetimo se, zaglavlje vezane liste delegata), sto ce se dogoditi??? Unutar funkcije ProsetajPoPoljuIZoviFunkciju, u liniji u kojoj se poziva callback metoda ustvari ce se redom pozvati sve callback metode koje su bile "wrappane" u vezanoj listi delegata! Drugim rijecima, za svaki element najprije ce se pozvati IspisNaKonzolu, a zatim IspisUProzor.

Vazno je uociti da je sve u gornjem primjeru bilo type-safe: npr. kada konstruiramo neki CallBackFn delegat, kompajler pazi na to da funkcije koje "wrappamo" imaju signaturu identicnu onoj koju smo naveli pri deklariranju delegata. Tj. u nasem slucaju obje metode moraju uzimati tri ulazna parametra (object, int i int) i obje metode moraju vracati void. Ako ovo ne bi bio slucaj, kompajler bi javio gresku.

U programu smo do sada delegate koristili samo za pozive statickih metoda. Medjutim, delegate mozemo koristiti i za pozivanje metoda instanci objekata. Jedino, moramo tada navesti instancu objekta nad kojim zelimo pozvati metodu.
Kad ovo uocimo, nastavak programa lako cemo razumjeti.

Eto, sada smo vidjeli otprilike kako se koristimo delegatima, cemu oni sluze, itd. No, kako su delegati interno, u CLR-u definirani??? Kako stvar funkcionira ispod "haube"??? O tome cete doznati vise u nekom od mojih sljedecih tekstova!

pozdrav svima od
math_baby
__________________
"Open source is an intellectual-property destroyer. I'm an American, I believe in the American Way. I worry if the government encourages open source and I don't think we've done enough education of policymakers to understand the threat."" -Jim Allchin, Microsoft operating system chief
math_baby is offline  
Odgovori s citatom
Old 28.08.2003., 18:47   #2
math_baby ima svoju kolumnu! Hura!
I ja sam razmišljao da otvorim svoju kolumnu pod nazivom C i C++ za početnike ali vidim da tebi to ide bolje!
__________________

MADE IN HEAVEN!
Anđeo is offline  
Odgovori s citatom
Old 28.08.2003., 21:34   #3
Quote:
Anđeo kaže:
math_baby ima svoju kolumnu! Hura!
I ja sam razmišljao da otvorim svoju kolumnu pod nazivom C i C++ za početnike ali vidim da tebi to ide bolje!
Podržavam te ako misliš nešto sa tom kolumnom... Ipak Math Baby nema kolumnu za C/C++ i to još za početnike
Mlaen is offline  
Odgovori s citatom
Old 05.09.2003., 19:45   #4
math_baby plz tell me koja je najbolja knjiga iz koje se moze lijepo naucit programirat u .NET-u?
laki is offline  
Odgovori s citatom
Old 06.09.2003., 11:06   #5
Quote:
lucky_voyager kaže:
math_baby plz tell me koja je najbolja knjiga iz koje se moze lijepo naucit programirat u .NET-u?
Sada, nakon izvjesnog vremena koje sam provela proucavajuci .NET i C#, mislim da bi apsolutnom pocetniku koji zeli postati ekspert na ovom podrucju pomoglo kada bi nabavio sljedece knjige (i citao ih upravo navedenim redoslijedom!):

1) Jesse Liberty: Programming C#, 3rd edition (dobra za pocetnike, pokriva dosta siroko podrucje)

2) Jeff Prosise: Programing .NET (izvrsno napisana, vrlo citljiva, ulazi malo dublje. Posebno je korisna onima koji zele nesto vise nauciti o ASP.NET-u, ali ne samo njima. Nevjerojatno se lako cita!)

3) Charles Petzold: Programming Windows with C# (vrlo iscrpno objasnjava kako pisati "prozorske" aplikacije u .NET-u. Charles Petzold je inace jedan od veterana Windows-programiranja. Njegova prijasnja knjiga objavljena je u 5 izdanja. Svatko tko zeli u C#-u pisati klasicne Windows-aplikacije bi trebao procitati ovu knjigu.

4) Jeffrey Richter: Applied Microsoft .NET Framework (za one koji zele znati pozadinu stvari, nauciti nesto vise o unutrasnjem radu CLR-a i .NET-a na nesto nizem nivou. Knjiga objasnjava npr. detalje o tome kako radi garbage collector, kako se kreiraju objekti, itd itd... Ova znanja korisna su onima koji vec znaju programirati ali zele pisati kvalitetne programe. Naslov knjige je, inace, potpuno pogresan - knjiga bi se trebala zvati: Unutarnji rad CLR-a")

5) Serge Lidin: Inside Microsoft .NET IL Assembler (za prave hakere, ide najnize moguce i objasnjava stvari na nivou Microsoftovog IL-medjukoda).


pozdrav,
math_baby
__________________
"Open source is an intellectual-property destroyer. I'm an American, I believe in the American Way. I worry if the government encourages open source and I don't think we've done enough education of policymakers to understand the threat."" -Jim Allchin, Microsoft operating system chief
math_baby is offline  
Odgovori s citatom
Old 06.09.2003., 18:43   #6
thnx math!
laki is offline  
Odgovori s citatom
Old 10.09.2003., 14:20   #7
Pitanje za autora kolumne.

Koja je razlika između >> i >>= u C#?

Zašto se išlo na case sensitive sintaksu, ako se izgradio potpuno novi jezik?

Koja je svrha Visual C# jezika u Visual Studio okruženju?

Pitam se pitam.
 
Odgovori s citatom
Old 10.09.2003., 22:56   #8
Re: Pitanje za autora kolumne.

Quote:
cirkusant kaže:
Koja je razlika između >> i >>= u C#?

Zašto se išlo na case sensitive sintaksu, ako se izgradio potpuno novi jezik?

Koja je svrha Visual C# jezika u Visual Studio okruženju?

Pitam se pitam.
1) Kada napises npr. izraz x = x >> y, tada se u tom izrazu x evaluira dvaput (prvi put pri racunanju x >> y, a drugi put pri rpidruzivanju). Ali, kada napises x >>= y, tada si postigao isti efekt, ali sa samo jednim evaluiranjem.

Dakle, razika je analogna onoj izmedju npr, + i +=

2) Ne znam zasto se islo na case sensitive sintaksu: vjerojatno zato su i C i C++ case-sensitive, a C# je "naljednik" tih jezika. S druge strane, VB.NET koji je nasljednik "starog" VB-a nije case-sensitive, jer to nije bio ni Visual Basic.

3) Pitas me koja je svrha C# jezika u Visual Studiu? Moram priznati da mi to pitanje nije bas jasno. Isto tako bi se moglo postaviti pitanje koja je svrha bilo kojeg jezika. Ne razumijem sto si htio reci...

pozdrav,
math_baby
__________________
"Open source is an intellectual-property destroyer. I'm an American, I believe in the American Way. I worry if the government encourages open source and I don't think we've done enough education of policymakers to understand the threat."" -Jim Allchin, Microsoft operating system chief
math_baby is offline  
Odgovori s citatom
Old 11.09.2003., 00:08   #9
Ja bih ti ipak predložio nešta drugo.
1.Learn Asp.Net In 21 Day(Iz iskustva znam da za 21 dan to ne moze)
2.Visual.Basic.Net Biblija
3.ASp.Net Profesionalno programiranje
4.Ado.Net Profesionalno programiranje (C#)

Quote:
math_baby kaže:
Sada, nakon izvjesnog vremena koje sam provela proucavajuci .NET i C#, mislim da bi apsolutnom pocetniku koji zeli postati ekspert na ovom podrucju pomoglo kada bi nabavio sljedece knjige (i citao ih upravo navedenim redoslijedom!):

1) Jesse Liberty: Programming C#, 3rd edition (dobra za pocetnike, pokriva dosta siroko podrucje)

2) Jeff Prosise: Programing .NET (izvrsno napisana, vrlo citljiva, ulazi malo dublje. Posebno je korisna onima koji zele nesto vise nauciti o ASP.NET-u, ali ne samo njima. Nevjerojatno se lako cita!)

3) Charles Petzold: Programming Windows with C# (vrlo iscrpno objasnjava kako pisati "prozorske" aplikacije u .NET-u. Charles Petzold je inace jedan od veterana Windows-programiranja. Njegova prijasnja knjiga objavljena je u 5 izdanja. Svatko tko zeli u C#-u pisati klasicne Windows-aplikacije bi trebao procitati ovu knjigu.

4) Jeffrey Richter: Applied Microsoft .NET Framework (za one koji zele znati pozadinu stvari, nauciti nesto vise o unutrasnjem radu CLR-a i .NET-a na nesto nizem nivou. Knjiga objasnjava npr. detalje o tome kako radi garbage collector, kako se kreiraju objekti, itd itd... Ova znanja korisna su onima koji vec znaju programirati ali zele pisati kvalitetne programe. Naslov knjige je, inace, potpuno pogresan - knjiga bi se trebala zvati: Unutarnji rad CLR-a")

5) Serge Lidin: Inside Microsoft .NET IL Assembler (za prave hakere, ide najnize moguce i objasnjava stvari na nivou Microsoftovog IL-medjukoda).


pozdrav,
math_baby
nristic is offline  
Odgovori s citatom
Old 12.09.2003., 14:10   #10
Re: Pitanje za autora kolumne.

Quote:
cirkusant kaže:

Zašto se išlo na case sensitive sintaksu, ako se izgradio potpuno novi jezik?
Ne kontam? Ti se zalazes ca case insensitive sintaksu ?
cunac is offline  
Odgovori s citatom
Old 12.09.2003., 15:32   #11
Cunac:
Quote:
Ne kontam? Ti se zalazes ca case insensitive sintaksu ?
Točno, za case insensitive sintaksu. Kome treba pokraj toliko mogućnosti imenovanja, override-a, pravila za imenovanje objekata (klasi, varijabli, ...), ... case sensitive sintaksa. Ko da smo ograničeni na 200 naziva za cijelu sintaksu. Npr. tko će pametan koristiti npr. naziv auto u 16 varijanti koje omogućava case sensitive sintaksa.

S druge strane koji je sustav više "error prone", case sensitive ili case insensitive?

Mišljenja!
 
Odgovori s citatom
Old 12.09.2003., 16:37   #12
Ti si cirkusant Pascal-aš ili Delphi-aš... garant...

No, ne da me smeta case sensitivity. Jednom dok se privikneš na to u C-u, dalje nema problema.

A onda ti je dalje svejedno u čemu ćeš radit.
Hallon is offline  
Odgovori s citatom
Old 12.09.2003., 16:46   #13
Hallon:
Quote:
Ti si cirkusant Pascal-aš ili Delphi-aš... garant...
Pa baš i ne. Više sam C++-aš, ali nisam ni to. Tko ili što sam ja? Šala. radi se o nečem, moglo bi se reći egzotičnom za naše prilike, ali ipak svakodnevno prisutnom.
 
Odgovori s citatom
Old 13.09.2003., 05:59   #14
Quote:
cirkusant kaže:
Cunac: Točno, za case insensitive sintaksu. Kome treba pokraj toliko mogućnosti imenovanja, override-a, pravila za imenovanje objekata (klasi, varijabli, ...), ... case sensitive sintaksa. Ko da smo ograničeni na 200 naziva za cijelu sintaksu. Npr. tko će pametan koristiti npr. naziv auto u 16 varijanti koje omogućava case sensitive sintaksa.

S druge strane koji je sustav više "error prone", case sensitive ili case insensitive?

Mišljenja!
case sensitive zato sto ti je u case insensitive
ime varijable
auto i Auto jednako
,a to nije intencija. Inace case insesitive vuce korjene iz proslosti kada nije bilo malih slova jer
a) to zahtjeva puno vecu matricu za slova
b) puno vise vremena za lleksiku ( zato su i varijable znale biti 2 slove , pa onda 8 ... )

ovo puno treba shvatiti u kontekstu 8K memorije je za superkompjuter
cunac is offline  
Odgovori s citatom
Old 13.09.2003., 16:35   #15
Delegati ispod "haube"!

Evo, proslo je dosta vremena otkad sam zapocela ovu moju kolumnu. U prvom nastavku govorila sam o delegatima koji nam u .NET-u daju type-safe nacin pozivanja callback funkcija. Takodjer sam obecala da cu u iducem "nastavku" opisati detaljnije kako rade delegati "ispod haube". No, prije nego pocnem, zeljela bih samo napomenuti da mi se u proslom listingu potkrala jedna greska. Naima, u funkciji StatickiCallBackovi umjesto linija

Kod:
cb += new Skup.CallBackFn(App.IspisNaKonzolu);
cb += new Skup.CallBackFn(App.IspisUProzor);
trebale su stajati linije

Kod:
cb += new Skup.CallBackFn(TestDriver.IspisNaKonzolu);
cb += new Skup.CallBackFn(TestDriver.IspisUProzor);
Do ove greske doslo je jer sam naknadno preimenovala klasu App u klasu TestDriver, ali sam zaboravila to ime svugdje promijeniti.

OK, sad idemo dalje. Proucimo li jos jednom primjer iz proslog listinga, vidjet cemo da su delegati zapravo laki za koristenje: jednostavno ih definiramo pomocu kljucne rijeci delegate, pomocu kljucne rijeci new konstruiramo instancu delegata i nakon toga pozivamo callback funkcije pomocu nama bliske "method call" sintakse, samo sto umjesto imena metode koristimo ime varijable koja referencira na delegatski objekt.

No, ono sto se pri svemu tome dogadja interno, nesto je malo slozenije: kompajler i CLR obavljaju dosta skrivenog posla da bi stvar nama izgledala jednostavno. No, sada dolazi trenutak prosvjetljenja:

Pogledajmo liniju koda iz proslog listinga kojom smo bili definirali nas delegatski objekt:

Kod:
public delegate void CallBackFn(Object value, int el, int brElem);
Kada kompajler vidi ovu liniju, on ustvari definira cijelu jednu klasu koja izgleda ovako:

Kod:
public class CallBackFn : System.MulticastDelegate
{
	//konstruktor
	public CallBackFn(Object target, int methodPtr);

	//Metoda s istim prototipom kao sto je zadano u source-kodu
	public void virtual Invoke(Object value, int el, int brElem);

	//Metode koje omogucuju asinkrono pozivanje callback funkcije
	public virtual IAsyncResult BeginInvoke(Object value, int el, int brElem,
AsyncCallback callback, Object object);

	public virtual void EndInvoke(IAsyncResult result);
}
Dakle, klasa koju generira kompajler (CallBackFn) ima 4 metode: konstruktor, Invoke, BeginInvoke i EndInvoke. U nastavku cu se koncentrirati na konstruktor i Invoke metodu.

Nadalje, nasa klasa CallBackFn je public, jer smo delegat definirali kao public. Da smo delegat definirali kao npr. protected ili private, tada bi i klasa CallBackFn bila protected ili private. Buduci da je nas delegat ustvari klasa, mozemo ga definirati ili ugnijezdenog unutar neke druge klase ili u global scope-u.

Primjetimo da je klasa CallBackFn naslijedjena iz bazne klase System.MulticastDelegate.
System.MulticastDelegate je klasa definirana u .NET biblioteci. Svi delegati u .NET-u derivirani su iz ove klase pa nas delegat CallBackFn (kao i svi ostali delegati!) naslijedjuje neke fieldove, propertiese i metode od klase System.MulticastDelegate. Od svih tih member-a najznacajnija su ova tri privatna fielda:

_target (koji je tipa System.Object)
_methodPtr (koji je tipa int)
_prev (koji je tipa System.MulticastDelegate)

Idemo redom:

_target referencira na objekt nad kojim ce se operirati kad se pozove callback metoda. Ovaj field se koristi za pozivanje callback metoda instanci objekata.

_methodPtr je cijeli broj koji CLR koristi da bi identificirao stvarnu callback metodu koju treba pozvati (dakle, _methodPtr ustvari glumi onaj pointer uobicajen u C-u)

_prev referencira na drugi delegatski objekt. Ovaj field je obicno null, ali nekad i ne mora biti!

Primjetimo da svi delegati imaju konstruktor koji uzima dva parametra: referncu na neki objekt i cijeli broj koji (glumeci pointer) referencira na pravu callback metodu. Medjutim, ako pogledamo program iz prvog listinga, vidjet cemo da se tamo, pri konstruiranju delegata pomocu kljucne rijeci new koriste konstrukti poput

new CallBackFn(App.IspisNaKonzolu);

ili

new CallBackFn(testObj.IspisUFile);

Kako je ovo moguce kad konstruktor delegata CallBackFn ocekuje drugacije parametre??? Jer, po ovome nasem se taj kod jednostavno ne bi mogao kompajlirati bez javljanja greske.

Medjutim, kompajler pri kompajliranju zna da se u tim nasim new naredbama konstruira delegat, pa prolazi kroz nas source-kod kako bi odredio na koji objekt i na koju metodu se nas delegat odnosi. Tada kompajler generira kod koji na "klasican" nacin poziva konstruktor od CallBackFn objekta proslijedjujuci mu kao parametar target referencu na objekt ciju callback funkciju zelimo pozvati (ili null, ako je metoda staticka!), a kao parametar methodPtr proslijedjuje mu token (adresu) zeljene metode.

Sto radi konstruktor delegata? Po njegovom pozivu, najprije se field _prev postavlja na null. Field _prev koristi se za kreiranje vezane liste objekata tipa MulticastDelegate. Za sada cu ignorirati ovo polje, ali u nekom od iducih nastavaka govorit cu o tzv. lancima delegata, pa ce tamo biti rijeci i o njemu.

Dakle, svaki delegat je u osnovi wrapper oko neke metode. Delegat je zapravo objekt nad kojim baratamo kada pozivamo callback metodu (ili vise njih).

Klasa MulticastDelegate definira i dva read-only propertyja: Target i Method.
Ako imamo referencu na neki delegatski objekt, tada mozemo procitati sto je zapisano u ova dva propertyja. Target nam vraca referencu na objekt nad kojim se poziva callback metoda. Ako je callbac metoda staticka, tada Target vraca null. Metod nam vraca objekt tipa System.Reflection.MethodInfo koji identificira callback metodu.

Ove informacije mozemo upotrijebiti na vise nacina. Npr. mozemo provjeriti referencira li neki delegatski objekt na metodu objekta nekog sasvim specificnog tipa:

Kod:
Boolean DelegatReferenciraNaMetoduZadanogTipa(MulticastDelegate d, Type type)
{
	return ((d.Target != null) && d.Target.GetType() == type);
}
Takodjer, mogli bismo npr. napisati kod koji provjerava ima li nasa callback metoda neko unaprijed zadano ime (npr. IspisUProzor):

Kod:
Boolean DelegatReferenciraNaMetoduZadanogImena(MulticastDelegate d, string methodName)
{
	return (d.Method.Name == methodName);
}
Naravno, ne treba ni reci da je ovako nesto u Javi nemoguce izvesti! No, pustimo to smece i idemo dalje!

Sad kad smo vidjeli kako se delegati konstruiraju, pogledajmo kako se pozivaju callback metode. U onom prvom listingu imali smo npr. ovakav programski isjecak:

Kod:
public void ProsetajPoPoljuIZoviFunkciju(CallBackFn fn)
{
	for (int el = 0; el < elementi.Length; el++)
	{
         	if (fn != null)
         	{
            	// ako je zadana bar jedna callback funkcija, pozovi je
            	fn(elementi[el], el + 1, elementi.Length);
         	}
      	}
}
Odmah nakon linije komentara dolazi linija u kojem se poziva callback metoda. Na prvi pogled, izgleda kao da pozivamo funkciju cije ime je fn kojoj prosljedjujemo tri parametra. Medjutim, funkcija s imenom fn ne postoji. Sto se onda dogadja???

Ponovo, zbog toga sto kompajler zna da je fn varijabla koja referencira na delegatski objekt, on generira kod koji poziva delegatovu Invoke metodu. Drugim rijecima, kad komajler vidi ovo:

Kod:
fn(elementi[el], el + 1, elementi.Length);
on generira kod kao da je pisalo ovo:

Kod:
fn.Invoke(elementi[el], el + 1, elementi.Length);
Da je ovo stvarno istina mozete provjeriti ako pomocu ILDasm dissasemblera dissasemblirate kod naseg programa. Da smo npr. iz C# koda eksplicitno pozvali Invoke, C# kompajler bi generirao ovu gresku: "error CS1533: Invoke cannot be called directly on a delegate". Dakle, C# kompajler ne dopusta da eksplicitno pozovemo Invoke; medjutim, drugi kompajleri bi mogli dopustiti da u svrhu pozivanja nase callback metode pozovemo Invoke. Zapravo, Visual Basic.NET upravo trazi od nas da eksplicitno pozovemo Invoke.

Prisjetimo se, na kraju da je kompajler definirao metodu Invoke onda kad je definirao klasu CallBackFn. Kad se pozove Invoke, ta metoda koristi privatne fieldove _target i _methodPtr u svrhu pozivanja zeljene callback metode nad zeljenim objektom. Primjetimo da je signatura metode Invoke ista kao i signatura koju smo upotrijebili pri definiranju delegata; tj. zbog toga sto je delegat CallBackFn uzimao tri parametra i vracao vrijednost void, zato i metoda Invoke uzima ista tri parametra i isto vraca vrijednost void.

Nadam se da sam sada malo rasvijetlila interni rad delegata (iako ne jos sasvim, jer ostaju jos i pozivanje vise callback funkcija zaredom, kao i asinkroni delegati, itd... ali, sve u svoje vrijeme!) Nego, ima li uopce nekoga tko ovo cita i razumije. Nadam se da ima... javite se stoga i recite svoje misljenje o ovoj mojoj maloj "kolumni".

pozdrav svima od
math_baby
__________________
"Open source is an intellectual-property destroyer. I'm an American, I believe in the American Way. I worry if the government encourages open source and I don't think we've done enough education of policymakers to understand the threat."" -Jim Allchin, Microsoft operating system chief
math_baby is offline  
Odgovori s citatom
Old 15.09.2003., 09:41   #16
Helou, ima li koga??? Ajde, ajde, javite se.... znam da tu i tamo ipak zavirite i ovamo...

math_baby
__________________
"Open source is an intellectual-property destroyer. I'm an American, I believe in the American Way. I worry if the government encourages open source and I don't think we've done enough education of policymakers to understand the threat."" -Jim Allchin, Microsoft operating system chief
math_baby is offline  
Odgovori s citatom
Old 15.09.2003., 14:35   #17
Bok, tu smo.
__________________

MADE IN HEAVEN!
Anđeo is offline  
Odgovori s citatom
Old 17.04.2004., 14:11   #18
Ne znam ima li zainteresiranih za nastavak ovoga?
Ako da, koje teme o .NET-u i C#-u biste voljeli ovdje vidjeti obradjene?

math_baby
math_baby is offline  
Odgovori s citatom
Old 17.04.2004., 14:16   #19
jesi sredila grešku na stranici 723 Programming Microsoft .NET
koju si imala oko 15.01.
GetObject
CreateInstance

nadam se da jesi
SETRA Samoborček is offline  
Odgovori s citatom
Old 17.04.2004., 14:24   #20
Quote:
SETRA Samoborček kaže:
jesi sredila grešku na stranici 723 Programming Microsoft .NET
koju si imala oko 15.01.
GetObject
CreateInstance

nadam se da jesi
Da, B. Rector mi je potvrdio da je bila greska. A otkud ti znas za to?

math_baby
math_baby is offline  
Odgovori s citatom
Odgovor


Tematski alati
Opcije prikaza

Kreni na podforum




Sva vremena su GMT +2. Trenutno vrijeme je: 02:12.