Oh, I had the very same problem. I understood the concept of events because I used them heavily in JavaScript but I just couldn’t justify the use of events in a C# application. I mean, I used server OnClick
etc, but I couldn’t understand why would I use events anywhere else.
Funny story actually, because I learnt it the hard way when I was working on my ORPG game. Consider following code:
class Player
{
private int health;
public int Health
{
get
{
if (health <= 0)
{
Die();
}
return health;
}
set
{
health = value;
}
}
public void Die()
{
// OMG I DIED, Call bunch of other methods:
// RemoveFromMap();
// DropEquipment(); etc
}
}
Makes sense, right? Player has no health so I'm calling Die()
. Die method is then doing whatever it is supposed to do - kill the player.
My problems started when I wanted to reuse this class in both Server and Client application of my ORPG game. It's quite easy to notice that Die()
method should do different things, depending on where the 'Kill' is performed - on server it should update all sorts of different data - on client it should i.e. do something with graphics.
Additionally - what if I wanted the Die()
method to do different things, depending on the type of Player? After all user controlled Players should do different things when they are killed compared to computer/AI controlled Players (NPCs).
And so, I was forced to use events:
class Player
{
public event DieHandler Die;
public delegate void DieHandler(Player sender, EventArgs e);
public virtual void OnDie(EventArgs e)
{
if (Die != null)
Die(this, e);
}
private int health;
public int Health
{
get
{
if (health <= 0)
{
onDie(new EventArgs());
}
return health;
}
set
{
health = value;
}
}
}
And now, when I create new player, I can assign any method to its DieHandler
:
Player player = new Player("Joe");
player.Die += Client.Players.PlayerDie;
Player npc = new Player("Cookie Monster");
npc.Die += Client.Npcs.NpcDie;
where Client.Npcs.Die
and Client.Players.Die
is one of following:
public void NpcDie(Player sender, EventArgs e)
{
//who hoo, I can be implemented differently
//I can even check if sender.Health <= 0
}
public void PlayerDie(Player sender, EventArgs e)
{
}
As you can see now we've got the flexiblity to attach any 'matching' method to our Die handler. We send the Player object as sender attribute and any defined EventArgs
in e. We can use EventArgs
to send additional information, i.e. - e.NameOfTheKiller
, e.LastHitAtTime
etc etc. The best thing is that you can define your own EventArgs
class so you can send additional info when you spawn your event.
Wow... this post is long. I hope you get it now.
So again - use events everywhere when you want to 'inform the external world' about some particular state of your object and handle this change appropriately. It will make your code more flexible and a lot easier to maintain.