Reputation: 2125
I'm having some issues here, I'm working with a class called Cell
and when I create each cell I want to raise an event OnCellCreated
which my IGameViewer
will attach to eventually. For some weird reason it doesn't work though, now I've bypassed this by instead calling IGameViewer.DisplayCell
in the constructor, but it's incredibly strange because it passes the exact same object reference from the constructor and it works, but when I try to do it with my event I will get a null object reference. So does anyone have any ideas?
Here's the code
class Cell
{
public delegate void CellChangedHandler(Cell cell);
#region Properties & Fields
private Mark markType = Mark.Empty;
private IGameViewer viewer;
public static event CellChangedHandler OnCellChanged;
public static event CellChangedHandler OnCellCreated;
public readonly Tuple<int, int> pos;
public Mark MarkType {
get { return markType; }
set
{
// Only allow changes to cells without a mark
if (markType.Equals(Mark.Empty))
{
markType = value;
OnCellChanged(this); //Model -> Viewer & Presenter, both can attach to this event
}
}
}
#endregion
#region Constructors
public Cell(IGameViewer viewer, Tuple<int, int> coords)
{
this.viewer = viewer;
this.pos = coords;
OnCellCreated(this); // <- This causes an object null reference exception to be thrown
viewer.DisplayCell(this); // <- This doesn't, even if I reverse the calling order
}
#endregion
}
Upvotes: 0
Views: 148
Reputation: 14836
As @Tigran answered, the problem is that no one has yet subscribed to the event. What were you expecting to happen by invoking the event on the constructor?
If you had followed the pattern to implement events in .NET classes this would have never happened.
Change your code to this:
class Cell
{
private Mark markType = Mark.Empty;
private IGameViewer viewer;
public static event EventHandler CellChanged;
public readonly Tuple<int, int> pos;
public Cell(IGameViewer viewer, Tuple<int, int> coords)
{
this.viewer = viewer;
this.pos = coords;
viewer.DisplayCell(this);
}
public Mark MarkType {
get { return markType; }
set
{
// Only allow changes to cells without a mark
if (markType.Equals(Mark.Empty))
{
markType = value;
OnCellChanged();
}
}
}
protected virtual void OnCellChanged()
{
var handler = this.CellChanged;
if (handler)
{
handler(this, EventArgs.Empty);
}
}
}
Upvotes: 0
Reputation: 186668
Check if there're subscribers for the event whenever raising it:
public Cell(IGameViewer viewer, Tuple<int, int> coords) {
this.viewer = viewer;
...
if (!Object.ReferenceEquals(null, OnCellCreated))
OnCellCreated(this);
...
}
Upvotes: 1
Reputation: 62248
Your OnCellCreated
event is null, because noone yet subscribed to it. And how can caller do that if you call it already in construcutor. ? One can not subscribe to the event of the instance if the instance is not yet created (you are in constructor)
You can create a CellFactory
class and add CellCretaed
event to the factory. You ask CellFactory
to create Cell instance, and CellFactory
after creation of it, raises an event. Naturally you have to subscribe to that event before calling factory method.
Upvotes: 3