Overly Excessive
Overly Excessive

Reputation: 2125

Null Object Reference when raising event in class constructor

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

Answers (3)

Paulo Morgado
Paulo Morgado

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

Dmitrii Bychenko
Dmitrii Bychenko

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

Tigran
Tigran

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

Related Questions