Sign in to follow this  
xxx_shinobi

[.net] Cannot understand events/delegates C#

Recommended Posts

Hello. I cannot understand events/delegates in C#. All I know is that delegates are something like c++ function pointers. My " Professional C# " book didnt help me much. Google tutorials also did not helped me. I still cannot see whole the picture. Thanks in advance

Share this post


Link to post
Share on other sites
What part you having trouble with? Events are things that happen, and delegates are the extra stuff you want to occur when the events happen. So if a Form has an OnClick event, the event signals when the form gets a click. A delegate is something you say you want to happen when the click happens.

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
What part you having trouble with? Events are things that happen, and delegates are the extra stuff you want to occur when the events happen. So if a Form has an OnClick event, the event signals when the form gets a click. A delegate is something you say you want to happen when the click happens.



Can you please show me as simple as possible example (just few lines to highlight your points).

Share this post


Link to post
Share on other sites
You have the right of it. Delegates are quite the c++ function pointers, just more powerful.

A delegate requires a method definition, (eg, void delegate ABC()), and can be applied to both static methods, or instance methods, which cannot be said for C++ function pointers. A delegate also, from initial observation, hold a strong reference to the instance it is created from (hence the use of proxy objects to hold additional data to pass to, or perform like a bind to other methods) A delegate, created, also provide asychrnous invokation, via BeginInvoke and EndInvoke (IIRC the method names) On a side note, I would strongly suggest trying the delegate asychrnous invokation to thread creation, since it is much easier to use, and take advantage of the .net threadpool.

Interesting, event are essentially a MulticastDelegate. Imagine MulticastDelegate as a list of delegates. You add and remove delegates to it via the += and -= . It also provide a quick way to check if there is any delegate in the list via the != null operation, and quick invokation via EventName(), which will invoke each delegate in the list. Of course, there are more to it, and some synchronization pitfalls to take care of...

Even more interesting, however, is that the .net platform, or rather the MSIL code, as of my maybe outdated understanding, does not provide special support nor understanding for Events, except as a flag tagged to the existing delegate, to be interpreted or handled specially by higher level languages.

I would highly recommend the book Expert .Net C++ Programming from APress. It would provide a good understanding of the workings of the .Net platform.

Share this post


Link to post
Share on other sites
Take a clock as an example. Imagine a clock object, which emits a tick every second. You want several other object to hear those ticks, i.e. you want the clock to notify the "tick listeners" by calling some method of theirs.

One approach would be to use interfaces (the Observer design pattern)


public class Clock
{
public void AddClockListener(IClockListener listener) { ... }
}

public interface IClockListener
{
void Tick();
}

public class Animation : IClockListener
{
public void Tick() { ... }
}

// Somewhere in a function
clock.AddClockListener(animation);




There are a few limitations/problems with using interfaces for this.
* If you wish to listen to multiple clocks, all ticks will have to go through the same Tick() method.
* The Tick() method must be public
* Tick() cannot be static
* Possible name clashes (other interfaces, base classes, ...)
* A listener interface can contain more than one method (e.g. the clock can be stopped and resumed, and there are extra ClockStopped() and ClockResumed() in the IClockListener interface); you would have to implement each of these methods in the Animation class, even if you do not care for those events)
* If multiple listeners are added to a clock, one must be careful how to call the Tick()-method of each: what if one listeners decides to unregister itself?

There are workarounds for these problems, e.g. Java uses inner/anonymous classes and adapter classes, and C# offers delegates/events.



public delegate void TickDelegate();

public class Clock
{
public event TickDelegate TickEvent;
}

public class Animation
{
public void Tick() { ... }
}

// Registering the animation
clock.TickEvent += new TickDelegate(animation.Tick);



A delegate is just a wrapper for a single function (which can have any visibility, can be static, etc.). The wrapping is done with "new TickDelegate(animation.Tick)".

An event is a container for delegates; you can add a delegate to an event with clock.TickEvent += aDelegate;

An event can be "fired", i.e. all registered delegates will be called in a safe manner. The firing is done with "if ( TickEvent != null ) TickEvent();" (not shown in example code).

Share this post


Link to post
Share on other sites
You are right, delegates are just type safe function pointers.
Events on the other hand are a "special" type of delegate. In fact they use delegates as the event handler.
Here is some simple code for a console app that I just whipped up.


namespace ConsoleApplication1
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
DelegateExample de = new DelegateExample();
de.Callback = new DelegateExample.MyCallback(DelegateCallback);
de.FireCallback();

EventExample ee = new EventExample();
ee.MyEvent += new EventExample.MyEventHandler(EventCallback);
ee.RaiseEvent();

Console.ReadLine();
}

public static void DelegateCallback()
{
Console.WriteLine("Called by delegate");
}

public static void EventCallback()
{
Console.WriteLine("Called by event");
}
}

public class DelegateExample
{
// declare the delegate
public delegate void MyCallback();

// create a holder for the delegate to use at a later time
private MyCallback m_myCallback;

// a property to set the callback
public MyCallback Callback
{
get {return m_myCallback;}
set {m_myCallback = value;}
}

public DelegateExample()
{

}

public void FireCallback()
{
if (m_myCallback != null)
{ // call the callback function
m_myCallback();
}
}
}

public class EventExample
{
// delcare the event handler
public delegate void MyEventHandler();

// delcare the event
public event MyEventHandler MyEvent;

public EventExample()
{

}

// fire the event
public void RaiseEvent()
{
if (MyEvent != null)
{
MyEvent();
}
}

}
}



The delegate and the event are doing the same thing, just choose your path.
Personally, I favor the use of delegates in non GUI uses. In my very un-scientic testing, I have found delegates much faster than events. I'm sure some will argue that. :D

Also, I believe that using delegates in .NET 2.0 has changed some, it the above code may not compile on the 2.0 Framework.

Share this post


Link to post
Share on other sites
OKIDOKY. Now I have a little understanding of this. I'll try to code something now to get a better understanding. You were all EXTREMELLY HELPFUL.

As I understand, delegates can be declared inside and outside to the class?
Another thing is EventArgs class. It must be inner to the event generator class or it's not a must?

Share this post


Link to post
Share on other sites
So is a delegate just another standard pattern that Microsoft decided needed a new name? This sounds a hell of a lot like signals and slots to me.

Share this post


Link to post
Share on other sites
When doing events you don't need a EventArgs class. The purpose of the class is to send data to work with inside the event handler. You have 2 common params for your events delegate. Those are:

object sender - what raised the event
EventArgs e - data that the event sends to the handler

You will see many implementations like this. However, You can easily make your own event args class if EventArgs is too generic for you. Here is a simple one.


public class ClockEventArgs : EventArgs
{
private int _hours;
private int _minutes;
private int _seconds;

public ClockEventArgs(int hours, int minutes, int seconds)
{
_hours = hours;
_minutes = minutes;
_seconds = seconds;
}

public int Hours
{
get
{
return _hours;
}
}

public int Minutes
{
get
{
return _minutes;
}
}

public int Seconds
{
get
{
return _seconds;
}
}
}




Now in the object that has the event, before it is fired you create a event args class to pass to the fireing call. Then in the handler you can access the properties through your eventargs class that comes in as a handler param.

Share this post


Link to post
Share on other sites
Quote:
Original post by smr
So is a delegate just another standard pattern that Microsoft decided needed a new name? This sounds a hell of a lot like signals and slots to me.


Its actually alot more than that. Its a pretty elegant solution to some of the problems with listeners (observer pattern) in java - that is, instead of you subscribing your entire class, and the notifier telling you what methods you *have* to implement for its interface (which for something like a moushandler is ***ing millions), you subscribe an individual method to an event on the notifier class.

so if all you care about is a 'click' event, you just provide a click method and subscribe it to the notifier's click delegate, and you dont have to implement stub methods for 'onMouseEntered' 'onMouseLeftArea' 'onDrag' 'onMouseMove'... (the notifier's delegate tells you what parameters it expects method it calls to have). which is damn useful.

also, you can call it whatever name you want so you wont run into problems where two interfaces have the same method that means different things to each - e.g. void clear(). So loathe though I am to admit it, M$ actually did a good thing with delegates. Its something Java cant do at present.

its called delegate because the notifier class doesnt attempt to provide any response to a particular event, it just delegates the response to subscribers

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this