C# i delegati

poruka: 11
|
čitano: 19.730
|
moderatori: Lazarus Long, XXX-Man, vincimus
1
+/- sve poruke
ravni prikaz
starije poruke gore
12 godina
neaktivan
offline
C# i delegati

DELEGATI


Da biste shvatili pojam delegata u C# jeziku morate znati već malo više od početaka u C#-u ,

 klase,objekte,metode itd....Ovo nije za početnike .Ovo je samo osvrt na puno pitanja o

delegatima koja mi se postavljaju kad netko počinje učiti C# ili recimo C++/CLI (CLR).
Dlegati se izvode u toku izvođenja(ispravak :))  tj. dinamički i tad se odlučuje koju metodu će pozvati.
Kod delegata se mora poštivati točno onako kako smo ga deklarirali, tako se i metode moraju

poklapati.Znači da se mora poštivati povratni tip delegata i metode kao i argumenti delegata

i metode.Znači oni su strogo specifični i zato sigurni pri pozivanju metode preko delegata.

Općenito :

public delegate (ovdje sad koji tip vraća) delegat_prvi(lista argumenata);

Znači :

 

public delegate void delegat_prvi(int a,int b);

Ova lista argumenata i povratni tip se mora poklapati sa metodom koju delegat poziva u toku

izvođenja programa !

 

Klasa s metodama static i instanca

 


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace Delegat_CSharp
{
    class DelegatskaKlasa
    {
      private  int var;

        public int Var
        {
            get { return var; }
          
        }

       public static void Funk1(int x)
        {
            Console.WriteLine("Pozvana je prva funkcija(metoda) {0}", x);
        }

      public  static  void Funk2(int x)
        {
            Console.WriteLine("Pozvana je druga funkcija(metoda) {0}", x);
        }
     public void Funk3(int x)
        {
            Console.WriteLine("Pozvana je treća funkcija(metoda) {0}", x + var);
        }
       public DelegatskaKlasa() { }
     public   DelegatskaKlasa(int x)
        {
            this.var = x;
        }


    }
}

 

Glavni program

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Delegat_CSharp
{
    class Program
    {
        public delegate void Deleg(int vrijednost);
        //ovdje deklariramo delegat Deleg
        static void Main(string[] args)
        {
            Deleg del = new Deleg(DelegatskaKlasa.Funk1);
            //ovdje stvaramo delegat del
            //koji pokazuje na prvu funkciju
            del(5);
            del += new Deleg(DelegatskaKlasa.Funk2);
            //ovdje samo dodajemo na drugu funkciju
            Console.WriteLine("-----------------------------------------");
            del(16);
            //da bismo pristupili trećoj funkciji moramo stvoriti
            //(instancu)
            //objekt o  preko kojeg pristupamo trećoj metodi.

            DelegatskaKlasa o =
                 new DelegatskaKlasa(10);
            //probajte bez argumenta jer imamo dva konstruktora
            Deleg del2 = new Deleg(o.Funk3);
            Console.WriteLine("----------------------------------------");
            del += del2;
            del(23);
            Console.WriteLine("---------------------------------------");
            del -= new Deleg(DelegatskaKlasa.Funk1);
            del(2345);       

        }
    }
}

 

 

Da bi razumjeli ovaj kod morate znati razliku između static i instance pristupa metodi .
Onaj tko ovo razumije tad može i proučiti kod.Ovo svakako nije za početnike već za one koji

su već malo napredovali u programiranju. Za C++ programere ima velike sličnosti s

pokazivačima na funkcije .


Delegati se mogu  operatorima + , -  dodavati i oduzimati.Uglavnom morate poštivati povratni

tip i argumente .
Računa o uklanjanju delegata vodi "garbage collection" automatizmom čiščenja memorije.
Delegate u C# -u koristimo za kreiranje Event-a .Znači delegati mogu biti usmjereni na više

metoda .Koja metoda se poziva preko delegata se odlučuje u toku izvođenja programa.
Naravno ,u ovom jednostavnom primjeru(ogledni primjer) mi smo sami odlučili koja metoda se

poziva ,ali se mogu staviti uvjeti da se ispune u toku izvođenja i ako je uvjet ispunjen

delegat se usmjerava na jednu metodu ,ako nije ispunjen ,usmjerava se na drugu metodu .

Ovdje se radi o "konzolnom" programiranju ,delegati imaju veće značenje u Win.Formama gdje

zajedno s Event-ima čine važan dio programiranja.

 

 

EVENT

 

Da biste recimo "bolje" ili lakše razumjeli "event-handler" objasniti ću samo zasad događaj u GUI-u(oblik koji se nalazi u Windows programiranju-recimo to tako ) radi jednostavnosti i standardnog event-a koji je sve prisutan u Windows programiranju.Koristi se dakle već definirani "defaultni" delegat ovog oblika :

public delegate EventHandler(object sender,EventArgs e);

Sad se sjetite da metoda koja se poziva preko ovog delegata mora imati iste parametre kao i delegat ,dakle :

 

object sender -objekt koji šalje zahtjev
EventArgs  e   - sadrži informacije o događaju

 

Sad možemo deklarirati delegat i event koji ćemo koristiti u klasi :

 

public delegate void SretanRodjendanDelegat(object sender ,EventArgs e);

public event SretanRodjendanDelegat  EventSretanRodjendan; //primjetite da deklaracija event-a završava samo s točka,zarez!!

 

To sve zajedno je deklaracija događaja,ostaje nam samo sad napraviti klasu i implementirati događaj koji smo gore napisali.Događaj koji će se izvršiti pri unosu datuma koji se odnosi na dan našeg rođenja a na sve ostale datume nema tog događanja nego ispis pozdrava.

Deklaracija event-a je slična deklaraciji delegata ,ovdje imamo ključnu riječ event ,prije toga modifikator pristupa ,zatim ime delegata u našem događaju i na kraju ime koje dajemo našem event-u kojeg ćemo koristiti pri "podizanju događaja"!

Ovo je vrlo pojednostavljen primjer ,čak i objašnjenja za događaj ali se može lijepo vidjeti kako implementirati event ,napisati metodu za delegat preko kojeg se i omogućuje događaj.
Sve u svemu vrlo jednostavno i ogoljeno objašnjenje bez previše filozofiranja uključuje delegat koji poziva metodu a sve preko event-a koji je u jednom trenutku zatražen.

Možda je ovo sve prejednostavno ali mislim da se bit kako i zašto koristimo delegate i event-a lijepo vidi.

Jednostavna klasa za implementaciju događaja :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace EventRodjendan
{
    class Unos
    {
        //deklaracija događaja
        public delegate void SretanRodjendanDelegat(object sender, EventArgs e);
        public event SretanRodjendanDelegat EventSretanRodjendan;
        //ovo je standardni oblik deklariranja Event-a ,dakle navođenje delegata
        // i davanje imena našem event-u

        private string ime;
        private string prezime;
        private DateTime datum;

        public DateTime Datum
        {
            get { return datum; }

//ovdje "podižemo događaj"
            set {
               
               
                datum = value;
                if (datum.ToString("dd MM") == DateTime.Now.ToString("dd MM"))
                {
                    if (EventSretanRodjendan != null)
                    {
                        EventSretanRodjendan(this, new EventArgs());
                    }
                  
                }
              
               
           
            }
        }


        public string Prezime
        {
            get { return prezime; }
            set { prezime = value; }
        }

        public string Ime
        {
            get { return ime; }
            set { ime = value; }
        }

        public string IspisImePrezime()//ovu metodu možemo i preklopiti s metodom ToString()
        {
            return this.Ime + " " + Prezime;
        }

    }
}


Main dio u kojem iniciramo događaj : 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EventRodjendan
{
    class Program
    {
        static void Main(string[] args)
        {
            Unos slavljenik = new Unos();
            Console.WriteLine("Upišite ime : ");           
                slavljenik.Ime = Console.ReadLine();        
                Console.WriteLine("Upišite prezime : ");
                slavljenik.Prezime = Console.ReadLine();
            Console.WriteLine("Upišite datum : ");
            slavljenik.EventSretanRodjendan +=
                new Unos.SretanRodjendanDelegat(Slavljenik);//ovdje implementiramo događaj
            try
            {
                slavljenik.Datum = DateTime.Parse(Console.ReadLine());
            }
            catch (Exception ex)
            {
                Console.WriteLine("Greška pri unosu ->{0}", ex.Message);
            }
            slavljenik.EventSretanRodjendan -=
               new Unos.SretanRodjendanDelegat(Slavljenik);
            Console.WriteLine();//ispisuje se samo pozdrav ako ne slavite
            //ako slavite ->sve se ispisuje  
           Console.WriteLine("Pozdrav , {0}", slavljenik.IspisImePrezime());

                
        }
        //ovo je metoda koja je u sastavu delegata koja se poziva
        //na temelju event-a

        static void Slavljenik(object sender, EventArgs e)
        {
            Console.WriteLine("Sretan rođendan Vama prije pozdrava{0}",
                ((Unos)sender).IspisImePrezime());

        }
    }
}

 

 

 

Ovo je jednostavno objašnjenje kako se implementira događaj ,na koji ga način izazivamo.
Pretpostavljajući da znate nešto o klasama,objektima ,statičkim metodama,instancama i objektima a također i o hvatanju izuzetaka koje ovom prilikom nisam niti objasnio nadajući se da niste početnici.Ovo nije proučavanješto se dešava ispod "haube" o Event-ima i delegatima ,ovo su primjeri na kojima možete razumjeti "delegate i evente" ,čemu služe ,kako se deklariraju i izvode na prejednostavan način u konzolnom programiranju.To je zasad sve od mene.

 

 

 

 

 

 

 

 

Private
Poruka je uređivana zadnji put pon 6.9.2010 21:03 (Private).
 
7 0 hvala 8
12 godina
offline
RE: C# i delegati
Private kaže...

Dlegati se izvode u toku prevođenja tj. dinamički i tad se odlučuje koju metodu će pozvati.

Misliš izvođenja?

Heart: _/\_/\_/\_/\_/\_/\_/\_/\_ Brain: __________________________
10 godina
neaktivan
offline
C# i delegati

umjesto instanciranja delegata u metodi,

deklaracija eventa je bolja opcija.

 

delegate void OnTestHandler(int i);

event OnTestHandler TestEvent;

 

void metoda(){

TestEvent += new OnTestHandler(testMetoda);

}

 

 
1 0 hvala 0
10 godina
neaktivan
offline
C# i delegati

event je delegate callback handler

 

...

 

Cool

 
1 0 hvala 0
12 godina
neaktivan
offline
RE: C# i delegati

Premješteno na početak Osmijeh

 

 

 

 

Private
Poruka je uređivana zadnji put pon 6.9.2010 21:04 (Private).
 
0 0 hvala 0
12 godina
offline
C# i delegati

Uglavnom, jako lijepo napisano! Nadopuni ovo sve u jedan post (ili prvih par gore jer ovaj spam izmedju postova smeta pri citanju).

Sticky :)

I'm going woo woo
 
0 0 hvala 1
11 godina
neaktivan
offline
C# i delegati

 

Kako si posta neki mini tut kako koristit event pretpostavljam da ih razumjes.

 

Ako nije problem bili mi moga pojasnit sljedece, naime kada se eventi koriste na "obican" nacin onda ne dolazi do memory leak-a ali u nekom slucaju to se desava

 

Ja san pronasa neku "definiciju" kada se se to dogadja i ona kaze

 

If the source object has a longer lifetime than the listener, and the listener doesn't need the events anymore when there are no other references to it, using normal .NET events causes a memory leak: the source object holds listener objects in memory that should be garbage collected.

 

ali ovo mi bas i nije sjelo pa ako nije problem bilo ko moga pojasnit i napisat primjer u kojem se javlja memory leak

 

 

 
0 0 hvala 0
12 godina
neaktivan
offline
RE: C# i delegati

Ukratko .....uvijek koristi += i -=  .

EventPoziv poziv = new EventPoziv();
EventIzvor izvor = new EventIzvor();

izvor.NasEvent += poziv.EventHandler;  //ovo je galvni uzrok problema
izvor.NestoRadi();

poziv = null;
// forsiramo garbage collection
GC.Collect();
GC.WaitForPendingFinalizers();

bez obzira što je poziv setiran na null objekt i dalje postoji i "množi se" zbog
operatora += i to je memory leak koji u nekom trenutku izaziva crash
 


//////////////////////////////////////


EventPoziv poziv = new EventPoziv();
EventIzvor izvor = new EventIzvor();

izvor.NasEvent += poziv.EventHandler;//ovdje počinje enkapsulacija
izvor.NestiRadi();
zvor.NasEvent -= poziv.EventHandler;
poziv = null;

 

Zato uvijek evente treba enkapsulirati s += i -= !!!

Ako si na to mislio.Vrlo skraćeno objašnjenje ali se drži boldanog.

 

Možda netko i bolje objasni  a detaljnije kad budem imao vremena .Postaj bar dio koda koji to izaziva gdje si to našao?

 

 

 

Private
Poruka je uređivana zadnji put uto 7.9.2010 23:14 (Private).
13 godina
neaktivan
offline
C# i delegati

Jel bi se ovakvo nešto moglo koristiti umjesto Timera za raisanje eventa svakih određeno x vremena?

Potpis ;)
Moj PC  
0 0 hvala 0
11 godina
neaktivan
offline
C# i delegati

Ma imam jednu knjigu koju koristim i u njoj sam procita da se to moze dogoditi ali tome je posvecena samo jedna recenica nema nikakvoga primjera kada se to dogadja :( a kao rjesenje problema su naveli weak events koji i nije bas da su mi dragi kad vidimo koliko "viska" koda moran dodavat pa sam isao malo dublje "kopat"

 

 

u medju vremenu san nasa jos par primjera tako da mislim da san skuzia :)

 

btw ima li neka metoda/program kojim se moze testirat dali u programu ima memory leakova ili sve ostaje na sposobnosti uocavanja ??

 

Znam da ovo drugo pitanje i nije bas dio teme al cisto usput

 
0 0 hvala 0
4 godine
neaktivan
offline
C# i delegati

 

 

 

Poruka je uređivana zadnji put pon 30.1.2017 21:49 (EricClapton).
 
0 1 hvala 0
1
Nova poruka
E-mail:
Lozinka:
 
vrh stranice