| ProgramatorCZ | Diskusní fórum | ASMDprojekt | Vtipy | JavaScript |
| Spolupracujeme: WebGuru | Komplikátor | MinaSite | Přidat k oblíbeným položkám | Nastavit jako výchozí stránku |
|
|
Práce v .NET Framework - Zástupci v rubrice DOTNET Vážení čtenáři. Chtěli bychom vám předložit několik příspěvků zaměřených na programování v Microsoft .NET Framework. Jejich úkolem bude ukázat na důležité a zajímavé rysy tohoto prostředí. Zatím máme v úmyslu věnovat se zástupcům, událostem a potom vláknům. K výkladu budeme používat programovací jazyk C#. V tomto příspěvku se zaměříme na práci se zástupci (angl. delegate) v .NET Framework. Zástupci v .NETZástupce je typově bezpečná reference (ukazatel) na metodu. K vytvoření zástupce musíme nejdříve mít potřebné informace o metodě (funkci) na kterou bude náš zástupce ukazovat. Jsou to: návratový typ metody, seznam parametrů, jejich datové typy a modifikátory (ref, out). Na základě těchto údajů deklarujeme nejprve zástupce jako datový typ. K tomu používáme klíčové slovo delegate. Chceme-li např. deklarovat zástupce na funkce, které jsou typu float, s jedním parametrem typu float, napíšeme public delegate float MyDelegate(float x); Takto jsme vytvořili nový datový typ zástupce nazvaný MyDelegate. Překladač generuje z tohoto typu třídu, z níž děláme konkrétní objekty, ukazatele na konkrétní funkce vyhovující typu zástupce. Příkazem MyDelegate DDveX=new MyDelegate(DveX); uděláme zástupce DDveX odkazujícího na funkci DveX. Vyvolání metody pomocí jejího zástupce zapíšeme jménem zástupce následovaným argumenty funkce uzavřenými ve výrazových (kulatých) závorkách. Zástupce též můžeme předat jako parametr při volání nějaké metody. Samozřejmě, že můžeme dělat zástupce na statické metody i na metody instance. V následujícím programu deklarujeme typ zástupce nazvaný MyDel. Z něho vytváříme v metodě Main dva zástupce f2 a f3 na funkce dvex a trix. Metodu dvex voláme s argumentem 4 pomocí zástupce v příkaze Console.WriteLine(f2(4));. V programu je dále metoda TiskFunkce, které při jejím volání předáváme zástupce na funkci a argument funkce.
using System; namespace Delegates {delegate float MyDel(float x);
class Class1 {
static void Main(string[] args) { MyDel f2=new MyDel(dvex); MyDel f3=new MyDel(trix); Console.WriteLine(f2(4)); TiskFunkce(f2,4); TiskFunkce(f3,5); } static void TiskFunkce(MyDel f,float x) { Console.WriteLine(f(x)); } static float dvex(float x){return 2*x;} static float trix(float x){return 3*x;} } } Vícečetní zástupci.V C# se zástupci používají při deklaraci událostí. Nastane-li v objektu událost, je volána jedna či více metod typu void, které událost obsluhují. Na tyto metody musí mít objekt, v němž událost nastala, reference. K tomu však stačí pouze jeden zástupce odvozený ze třídy Systém.MulticastDelegate. Takovému zástupci budeme říkat zástupce vícečetný. Nyní si ukážeme základní rysy vícečetných zástupců. Práci s událostmi se budeme věnovat v dalším příspěvku. Seznam referencí vícečetného zástupce plníme metodou Combine public static Delegate Combine(Delegate a, Delegate b);
Pro kompozici zástupců lze navíc v C# s výhodou používat přetížený operátor + (tedy místo metody Combine). Metodou Remove public static Delegate Remove(Delegate source, Delegate value);
lze naopak ze seznamu referencí určitého zástupce source odejmout referenci value. K odstranění zástupce ze seznamu lze navíc v C# s výhodou používat přetížený operátor -. Seznam referencí umístěných v zástupci lze jeho metodou GetInvocationList načíst do pole typu Delegate. Zdůrazněme, že delegate je klíčové slovo C#, zatímco Delegate je datový typ .NET Framework. Pomocí vlastnosti zástupce Target lze referencovat objekt, na jehož metodu zástupce ukazuje. Pomocí vlastnosti zástupce nazvané Metod můžeme získat informace o referencované metodě.
public object
Target { get; } Příklad: Ve třídě CDemo jsou metody Met1 a Met2, podle kterých jsme udělali zástupce Dlg. Dále děláme ze třídy CDemo dva objekty demo1, demo2 a zástupce b který referencuje demo1.Met1 a ještě zástupce c referencující demo1.Met2. Do zástupce a kombinujeme b a c. Následně vytvoříme zástupce d na demo2.Met2 a opět jej vložíme do zástupce a. Potom procházíme cyklem pole delegátů získané voláním metody a.GetInvocationList() a vypisujeme jméno objektu v němž je referencovaná metoda a jméno této metody. Nakonec ze seznamu referencí zástupce a odstraníme referenci b a opět projdeme zbylé reference cyklem.
using System; namespace MultiDelegates { delegate void Dlg(string s); class Class1 {
[STAThread] static void Main(string[] args) { Dlg a,b,c,d; CDemo demo1=new CDemo("Prvni"); CDemo demo2=new CDemo("Druhy"); b=new Dlg(demo1.Met1); c=new Dlg(demo1.Met2); a=(Dlg)Delegate.Combine(b, c); // a("nazdar"); d=new Dlg(demo2.Met2); a+=d; a("nazdar"); Console.WriteLine("Procházíme seznam delegátů"); Delegate[] dp=a.GetInvocationList(); foreach(Delegate di in dp) { Console.WriteLine(di.Target.ToString() + " : " + di.Method.Name); } a=a-b; dp=a.GetInvocationList(); Console.WriteLine("Procházíme seznam delegátů po odstranění zástupce b"); foreach(Delegate di in dp) { Console.WriteLine(di.Target.ToString() + " : " + di.Method.Name); } } } class CDemo { string name; public CDemo(string name) { this.name=name; } public void Met1(string s1) { Console.WriteLine("Jsem metoda Met1 objektu " + name + " a volali jste mne s parametrem " + s1); } public void Met2(string s2) { Console.WriteLine("Jsem metoda Met2 objektu " + name + " a volali jste mne s parametrem " + s2); } public override string ToString() { return name; } } } Výstup programu: Jsem metoda Met1 objektu Prvni a volali jste mne s parametrem nazdar Jsem metoda Met2 objektu Prvni a volali jste mne s parametrem nazdar Jsem metoda Met2 objektu Druhy a volali jste mne s parametrem nazdar Procházíme seznam delegátů Prvni : Met1 Prvni : Met2 Druhy : Met2 Procházíme seznam delegátů po odstranění zástupce b Prvni : Met2 Druhy : Met2 Autor: Jiří Makovička e-mail: jmakov@natur.cuni.cz web:
|
|
|
 
(c) Systém Jan Sova, Design David Krásenský a Jan Sova
Se svými dotazy či problémy se obracejte na diskusní
fórum.
Časopis je součástí projektu Programator