Delegate

T

Tony Johansson

Hello!!

Below is a program copied from a book.
The program is easy but there is one thing about the program that I would
like to have some more info about.

Assume that you have for example 10 cars in the array gameCars.
Assume also that you want to subscribe to an event for some cars located in
the array gameCars.

Now to my question. There are two metods called Subscribe and Unsubscribe.
When you subscript to an event for one or more cars located in the array
gameCars how does the program know which cars
you subscribe to because you don't include any this or will this object this
be passed invisible to us. or is it in another way.
The publisher is class GameController and subscriber is class Car.
Just below is the method Subscribe which is the key to my question. Here you
just add another instance of the event object MoveRequest and pass the
eventhandler which should take care of the event when fired from the
publisher GameController
public void (GameController controller)
{
controller.OnMoveRequest += new MoveRequest(MoveRequestHandler);
}


//Begin is the complete Program
//***********************
using System;
enum MoveRequestType { FastForward, SlowForward, Reverse };

class MoveRequestEventArgs : EventArgs
{
private MoveRequestType request;

public MoveRequestEventArgs(MoveRequestType initRequest) : base()
{
request = initRequest;
}

public MoveRequestType Request
{
get
{
return request;
}
}
}

public delegate void MoveRequest(object sender, MoveRequestEventArgs e);

class GameController
{
public event MoveRequest OnMoveRequest;
Car[] gameCars = new Car[10];
string carName;
int speedParam = 0;
int carCounter = 0;
int carNumber = 0;

public void Run()
{
string answer;
Console.WriteLine("Please select from the following menu: ");
Console.WriteLine("A)dd cal");
Console.WriteLine("C)ar. Subscribe to events");
Console.WriteLine("U)nsubscribe from events");
Console.WriteLine("L)ist cars in current game");
Console.WriteLine("F)ast forward");
Console.WriteLine("S)low forward");
Console.WriteLine("R)everse");
Console.WriteLine("T)erminate");

do
{
Console.WriteLine("Select new option:");
answer = Console.ReadLine().ToUpper();

switch (answer)
{
case "A" :
Console.WriteLine("Enter name of the new car: ");
carName = Console.ReadLine();
Console.Write("Enter car speed parameter of the new
car: ");
speedParam = Convert.ToInt32(Console.ReadLine());
gameCars[carCounter] = new Car(speedParam, carName);
carCounter++;
break;

case "C":
Console.WriteLine("Enter array index of car you want to
subscribe to events: ");
carNumber = Convert.ToInt32(Console.ReadLine());
gameCars[carNumber].Subscribe(this);
break;

case "U":
Console.Write("Enter array index of car you want to
unscribe from event: ");
carNumber = Convert.ToInt32(Console.ReadLine());
gameCars[carNumber].Unsubscribe(this);
break;

case "L":
for (int i= 0; i<carCounter; i++)
Console.WriteLine(gameCars);
break;

case "F":
if (OnMoveRequest != null)
OnMoveRequest(this, new
MoveRequestEventArgs(MoveRequestType.FastForward));
break;

case "S":
if (OnMoveRequest != null)
OnMoveRequest(this, new
MoveRequestEventArgs(MoveRequestType.SlowForward));
break;

case "R":
if (OnMoveRequest != null)
OnMoveRequest(this, new
MoveRequestEventArgs(MoveRequestType.Reverse));
break;

case "T":
break;
default:
Console.WriteLine("Invalid choice. please try again");
break;
}
}while(answer != "T");
}
}

class Car
{
private int distance;
private int speedParam;
private string name;

public Car(int initSpeedParam, string initName)
{
speedParam = initSpeedParam;
distance = 0;
name = initName;
}

public void Subscribe(GameController controller)
{
controller.OnMoveRequest += new MoveRequest(MoveRequestHandler);
}

public void Unsubscribe(GameController controller)
{
controller.OnMoveRequest -= new MoveRequest(MoveRequestHandler);
}

public void MoveRequestHandler(object sender, MoveRequestEventArgs e)
{
switch (e.Request)
{
case MoveRequestType.SlowForward:
distance += speedParam;
Console.WriteLine("Car name: " + name + "Moving slowly.
Distance: " + distance);
break;
case MoveRequestType.FastForward:
distance += speedParam * 2;
Console.WriteLine("Car name: " + name + "Moving fast.
Distance: " + distance);
break;
case MoveRequestType.Reverse:
distance -= 5;
Console.WriteLine("Car name: " + name + "Reversing Distance:
" + distance);
break;
}
}

public override string ToString()
{
return name;
}
}

class Tester
{
public static void Main()
{
GameController controller = new GameController();
controller.Run();
}
}

//Tony
 
J

Jon Skeet [C# MVP]

Tony Johansson said:
Below is a program copied from a book.
The program is easy but there is one thing about the program that I would
like to have some more info about.

Assume that you have for example 10 cars in the array gameCars.
Assume also that you want to subscribe to an event for some cars located in
the array gameCars.

Now to my question. There are two metods called Subscribe and Unsubscribe.
When you subscript to an event for one or more cars located in the array
gameCars how does the program know which cars
you subscribe to because you don't include any this or will this object this
be passed invisible to us. or is it in another way.

The GameController doesn't really know what is subscribing to it - it
just gets a delegate instance to effectively add to the list of
delegate instances to call at the appropriate time. However, the
delegate instances in question all use MoveRequestHandler as the
action. That's an instance method, so when you subscribe to an event
using it there's an object associated with the delegate as well (the
*target* of the delegate). It's implicitly "this" - the code:

controller.OnMoveRequest += new MoveRequest(MoveRequestHandler);

is equivalent to:

controller.OnMoveRequest += new MoveRequest(this.MoveRequestHandler);

You could subscribe using a *different* car as the target of the
delegate:

controller.OnMoveRequest += new MoveRequest(other.MoveRequestHandler);

If this isn't clear, try reading:

http://pobox.com/~skeet/csharp/events.html
and
http://www.codeproject.com/KB/cs/event_fundamentals.aspx
 
M

Marc Gravell

The "this" is implicit, since Subscribe, Unsubscribe and
MoveRequestHandler are all instance methods. Hence, this is equivalent
to the following ["this" added]. Each delegate knows about the
specific instance *and* the method involved in the delegate's
construction. Obviously things are slightly different if one-or-more
of the methods is static.

Does that answer the question?

Marc

public void Subscribe(GameController controller)
{
controller.OnMoveRequest += new
MoveRequest(this.MoveRequestHandler);
}


public void Unsubscribe(GameController controller)
{
controller.OnMoveRequest -= new
MoveRequest(this.MoveRequestHandler);
}
 

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