Learning delegates and events

M

Mark Allison

Hi,

I am new to C# and want to create my own events within a console app.
However I am struggling mentally with this, and have looked at the MSDN
documentation but I am drawing a blank. Is there anywhere on the net
that shows a very basic delegate and a very basic event? Some nice
simple example code is what I'm looking for with no fluff around it.

Thanks!

--
Mark Allison, SQL Server MVP
http://www.markallison.co.uk

Looking for a SQL Server replication book?
http://www.nwsu.com/0974973602m.html
 
R

Ravichandran J.V.

I will definitely post a simple article on both today but, in the
meanwhile, I am quite sure you should find this helpful.

The delegate is a type which is capable of encapsulating a method
signature. The delegate can be used in conjunction with events. An event
is a type that is usually declared inside the class.


public class MyClass
{
// The delegate that points to the method to invoke. The
// method's return type in this case is 'void'.
public delegate void MyDelegate();
// If the method that is going to handle the event
// (MyMethod in this case) takes parameters, declare
// the delegate as follows
public delegate void MyDelegate(int i);
// The event is of type MyDelegate
public event MyDelegate MyEvent;
public MyClass()
{
// Attach the event to the delegate
this.MyEvent+=new MyDelegate(MyMethod);
}
// This is the method that acts as the event procedure.
public void MyMethod()
{
// Handle the event here.
}
}

with regards,


J.V.Ravichandran
- http://www.geocities.com/
jvravichandran
- http://www.411asp.net/func/search?
qry=Ravichandran+J.V.&cob=aspnetpro
- http://www.southasianoutlook.com
- http://www.MSDNAA.Net
- http://www.csharphelp.com
- http://www.poetry.com/Publications/
display.asp?ID=P3966388&BN=999&PN=2
- Or, just search on "J.V.Ravichandran"
at http://www.Google.com
 
M

Mark Allison

Thanks,

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?

When you attach the event to the delegate are you "firing the event",
raising 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?

I'm sorry but your very simple example just confused me even more.


--
Mark Allison, SQL Server MVP
http://www.markallison.co.uk

Looking for a SQL Server replication book?
http://www.nwsu.com/0974973602m.html
 
J

Jon Skeet [C# MVP]

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.
 
J

Jon Skeet [C# MVP]

Jon Skeet said:
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.

<snip>

Oops - something I meant to add: the C# compiler doesn't use the
"raise" operation on an event, but that's another operation the CLI
defines.
 
T

Thomas Edison

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?

Does the following help?

using System;

public class EventRaiser
{
public void RaiseEvent() {
DemoEvent(123);
}

public event DemoEventHandler DemoEvent;
}

public delegate void DemoEventHandler(int n);

public class EventSubscriber
{
EventRaiser eventRaiser;

public void SubscribeToAndRaiseEvent() {
eventRaiser = new EventRaiser();
eventRaiser.DemoEvent += new DemoEventHandler(raiser_DemoEvent);

eventRaiser.RaiseEvent();
}

void raiser_DemoEvent(int n) {
Console.WriteLine(String.Format("In raiser_DemoEvent. n = {0}.", n));
}
}

public class ProgramEntryPoint
{
static void Main() {
EventSubscriber subscriber = new EventSubscriber();
subscriber.SubscribeToAndRaiseEvent();

Console.Read();
}
}
 
M

Mark Allison

Thanks Thomas,

What I don't understand is that the Client Raised the event. I want the
Client to subscribe to the event and listen to see if anything
interesting happens in EventRaiser.

Let me describe my scenario. I have a class which I would like to raise
events from, these events need to pass a string. I have another class
which will listen for these events, and then print the string to the
Console using Console.WriteLine.

How would I do that? I don't want the subscribing class to raise the
event, I want it to react to an event, i.e. listen to an event.

Am I missing something here? Is it all in the semantics? I'm still not
getting it...

--
Mark Allison, SQL Server MVP
http://www.markallison.co.uk

Looking for a SQL Server replication book?
http://www.nwsu.com/0974973602m.html
 
C

C# Learner

Thanks Thomas,

What I don't understand is that the Client Raised the event.

Technically speaking, the client didn't raise the event: the client *asked*
the server to raise the event, and the server raised it.

I wrote the code like this to make it easy to understand.
How would I do that? I don't want the subscribing class to raise the
event, I want it to react to an event, i.e. listen to an event.

Take my example and remove the part where the client asks the server to
raise an event. Arrange matters so that the server raises the event as a
result of something other than the client asking it to. :)

P.S.: Two corrections to my code:

o EventRaiser.RaiseEvent should check that the event has subscribers
before trying to raise it:

public void RaiseEvent() {
if (DemoEvent != null) {
DemoEvent(123);
}
}

o eventRaiser doesn't need to be a member of EventSubscriber; it could
be a local variable and achieve the same result.
 
J

Jon Skeet [C# MVP]

Mark Allison said:
What I don't understand is that the Client Raised the event. I want the
Client to subscribe to the event and listen to see if anything
interesting happens in EventRaiser.

The client raising the event (or rather, calling a method which happens
to raise the event) is incidental to these examples - it's just a way
of demonstrating things.
Let me describe my scenario. I have a class which I would like to raise
events from, these events need to pass a string. I have another class
which will listen for these events, and then print the string to the
Console using Console.WriteLine.

How would I do that? I don't want the subscribing class to raise the
event, I want it to react to an event, i.e. listen to an event.

Just define a delegate which takes a string, and then have an event of
that type. When you choose to raise the event is up to you.
 
J

Jon Skeet [C# MVP]

Mark Allison said:
I sent you private mail, I hope you don't mind. :)

No problem. For the benefit of others, here's the example I've sent
though, showing the event being raised separately from the client code:

using System;
using System.Threading;

delegate void StringDelegate (string value);

class EntryPoint
{
static void Main()
{
EventGenerator eg = new EventGenerator();
Client c = new Client();
eg.SomeEvent += new StringDelegate(c.CatchEvent);

eg.Start();
}
}

class EventGenerator
{
public event StringDelegate SomeEvent;

public void Start()
{
while (true)
{
if (SomeEvent != null)
{
SomeEvent(DateTime.Now.ToString());
}
Thread.Sleep(1000);
}
}
}

class Client
{
public void CatchEvent (string value)
{
Console.WriteLine (value);
}
}
 
J

Jon Skeet [C# MVP]

Mark Allison said:
Guess what? The penny dropped! :) I had one of those moments when the
fog dissipated and I basked in the light of c# delegate and event
handling understanding.

Thanks for your patience! My app works beautifully! :)

Excellent - glad it's all working :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top