Programujeme v jazyku C# II. Diel 13. – Udalosti II

Michal Čižmár  /  22. 03. 2006, 00:00

Dnes pôjdeme trochu viac do hĺbky pri programovaní delegátov. Ak máte náhodou aj po minulom článku ešte stále hmlistú predstavu o delegátoch, tak dnes ich už určite pochopíte, asi aj keby ste nechceli :-) Povieme si niečo aj o MSIL

Keďže tento diel má zaujímavé číslo, rozhodol som sa ho urobiť trochu iným. Aby si na svoje prišli v tomto seriály aj zabehnutí programátori v C#. Pozrieme sa na to, čo sa deje vo vnútri programu, ktorý používa delegátov.
 
>>Aký dátový typ je delegate?

Už v minulom dieli som spomínal, že delegáti majú čo dočinenia s triedami. Túto informáciu som ale iba niekde čítal a chcel som si overiť ako sa naozaj veci majú. Potom som si spomenul, že predsa existuje .NET MSIL Disassambler, ktorý umožňuje preložiť existujúci .exe súbor do medzi-jazyka MSIL, ktorý tvorí základný kameň celej platformy .NET.

 

Poznámka I: Zdrojové súbory všetkých programovacích jazykov, ktoré podporuje .NET sa najprv preložia do medzi-jazyka MSIL(Microsoft intermediate language), ktorý sa skladá zo základných inštrukcií ako napr. načítaj hodnotu premennej, skoč na funkciu, porovnaj a podobne, pričom ešte stále nie sú závislé na architektúre CPU.  A až potom sa jazyk MSIL prekladá na spustiteľný program. Ak ste zdatný programátori a máte dosť času, tak si môžete dokonca vymyslieť vlastný programovací jazyk (syntax) pre .NET a postaviť ho na základoch MSIL. Už aj s takýmito projektmi som sa stretol.

 

Poznámka II.:

a.) Ak máte nainštalovaný .NET Framework SDK, tak MSIL disassambler nájdete takto:

Start-> Programs-> Microsoft .NET Framework SDK Vx.y -> Tools -> MSIL Disassambler

b.) Alebo priamo v SharpDevelop
Tools-> IL Dasm
 

>>Malý experiment s MSIL Disassambler.

Vytvoril som tento jednoduchý program, ktorý iba deklaruje, vytvorí a volá delegáta.

 
Príklad 13.1
using System;
class MainClass
{
    delegate int TestDelegate(string msg, int num);
           
    public static void Main(string[] args)

    {          
            TestDelegate delegat =

            new TestDelegate(Pokus);
     
            delegat("",5);

           //delegat.Invoke("",5); = iny sposob

     }
     private static int Pokus(string msg, int num)
     {
         return 0;  
     }
}

Vidíte, že program naozaj nič užitočné nerobí, ide mi len o to aby ste videli, čo sa v skutočnosti deje, keď sa vytvára delegát v našom príklade s menom TestDelegate. Takže som disassambloval tento program a výsledok si môžete pozrieť na screenshote1




Tak a je to tu! :-). Máme dôkaz, že naozaj delegete je len “syntaxický cukor“, ktorý za nás vytvorí sám triedu, ktorá je dedičom triedy MulticastDelegate, ktorá zapuzdruje dva hlavné parametre a to : meno objektu a meno jednej z jeho metód, ktoré delegát ma zastupovať.

Veď pozrite sa na dva konštruktory tejto triedy:



Asi Vás hneď napadlo, že jeden automaticky kompilátor vyberie, podľa toho, či sa vytvára delegát pre statickú metódu alebo pre objekt. Ale o to sa programátor, použitím delegate nemusí starať.

 >>Terminologické okienko :-)

Teraz, keď sme prenikli do tajov delegátov, by sme si mali ujasniť používanú terminológiu.

Prečítal som už viacero článkov, manuálov a kníh, kde sa písalo o delegátoch v C# a zistil som, že ešte stále nie je ujasnená terminológia v tejto oblasti. Je to asi tým, že “syntaxický cokor“ ako je delegate je novinka.

 

Keďže ale vieme, že delegát nie je nič inšie ako trieda, odporúčam používať nasledujúcu terminológiu, ktorá je podobná ako pri triedach.

 
Deklarácia
delegáta (s menom TestDelegate)
Napr.:   delegate int TestDelegate(string msg, int num);
 
Vytvorenie inštancie delegáta (s menom delegat  a typu TestDelegate)
Napr.: TestDelegate delegat =new  TestDelegate(Pokus);
 

Môžete sa bežne stretnúť s tým, že programátori používajú pojem delegát aj pre jeho deklaráciu, aj pre jeho inštanciu a vtedy si musíte dať pozor o čom sa naozaj točí :-)


>>Pokračujeme v experimente s MSIL!

Taký jednoduchý program a čo všetko sa dá z neho dozvedieť, pekné čo? Pokračoval som v mojom skúmaní a zaujímalo ma, čo sa deje vo vnútri metódy Main() na úrovni MSIL. Tu máte screenshot2:



Len stručne :
 
a.) Všimnite si to, že delegát je len trieda potvrdzuje aj inštrukcia newobj, ktorá sa volá pri vytváraní inštancie delegáta, pričom sa volá aj jeden z jeho konštruktorov .ctor.

b.) Samotné volanie metódy inštancie delegáta, ktorú zastupuje -> delegat(), je nahradené volaním metódy delegat.Invoke(), ktorú zdedil po triede MulticastDelegate.
 
c.) Invoke() môže volať aj priamo v programe, ako som naznačil v príklade na začiatku, len je to zakomentované, takže sa to samozrejme vôbec neprejavilo v MSIL.
 

>>Čo bude nabudúce?

Zas prepnem na štandardnú obtiažnosť článkov :-) t.j. mierne pokročilý a ukážeme si ako použiť delegáta ako parameter inej metódy, názorne na viacerých príkladoch.

 

Michal Čižmár

micitn@orangemail.sk

Neprehliadnite: