Mark Allison said:
OK, let me put this into my own words, and then you can slap me down. ;-)
You create a delegate called public delegate void MyDelegate(int i) -
this delegate runs code with the same sig. Cool, got that.
You then define your event as follows:
public event MyDelegate MyEvent;
I don't acutally understand the above line of code. What is that
effectively declaring?
It's effectively declaring a field, an event and two operations on the
event. An event has add/remove operations, each of which take a
compatible delegate instance as their parameter. The C# compiler adds
these in by default if you don't specify them. The exact naming and
semantics are unfortunately not defined in the specification, but it's
something like:
public event SomeDelegate Name;
translates to
// This is what stores the actual invocation list.
private SomeDelegate _Name;
// This is the public side of things
public event SomeDelegate Name
{
add
{
lock (this)
{
_Name += value;
}
}
remove
{
lock (this)
{
_Name -= value;
}
}
}
See
http://www.pobox.com/~skeet/csharp/threads/lockchoice.shtml for a
more thread-safe version.
When you attach the event to the delegate are you "firing the event",
raising the event?
No, you're subscribing to the event.
I want the event to be listened to from another class
altogether from this one. How do I get that other class to listen to
events in this class?
Here's a two-class (plus delegate definition) example:
using System;
delegate void TestDelegate();
class EventHolder
{
public event TestDelegate Foo;
public void RaiseEvent()
{
if (Foo != null)
{
Foo();
}
}
}
class Client
{
static void Main()
{
EventHolder holder = new EventHolder();
holder.Foo += new TestDelegate(First);
holder.Foo += new TestDelegate(Second);
holder.RaiseEvent();
}
static void First()
{
Console.WriteLine("First");
}
static void Second()
{
Console.WriteLine("Second");
}
}
Note that the event delegate ends up as a multicast delegate (I think
single cast delegates are effectively obsolete) so you can effectively
make one delegate out of lots - it just ends up calling them all in
turn.
I was confused for a while as to what the difference between a delegate
and an event was - and basically it's an encapsulation issue. An event
really just encapsulates adding and removing delegates (handlers). A
delegates itself has that and the ability to be fired. Note that from
Client I couldn't have called holder.Foo() directly - I can only add
and remove delegates. Similarly, events can be implemented without a
straight delegate member variable - some classes may have hundreds of
potential events, most of which aren't subscribed to by anything. In
that case, it makes sense to have some other data structure (eg a list
of events which *have* been subscribed to). The event encapsulation
allows that to happen.