C# C# Objects Loops and Final Touches Playing the Game

Christian Fincher
Christian Fincher
3,065 Points

NullReferenceException Tower

Howdy!

So I'm all set to run the code and everything compiles. However, upon execution, it appears as though the Title error appears and I'm currently unsure as to why.

Unhandled Exception System.NullReferenceException: Object reference not set to an instance of an object
at TreehouseDefense.Tower..ctor (TreehouseDefense.MapLocation location) <0x404e6f10 + 0x0001d> in <filename unknown>:0
at TreehouseDefense.Game.Main () <0x404e5d50 + 0x0064b> in <filename unknown>:0

Creation of my towers in Game.cs

Tower[] towers = {
              new Tower(new MapLocation(1, 3, map)),
              new Tower(new MapLocation(3, 3, map)),
              new Tower(new MapLocation(5, 3, map))
            };

            Level level = new Level(invaders)
            {
              Towers = towers
            };

Tower Class code.

private readonly MapLocation _location;
    private readonly Path _path;
    private const int _range = 1;
    private const int _power = 1;


    //Check to see if the Tower on the Path
    //Map Location Class, Invader, and Path Class

    public Tower(MapLocation location)
    {
      bool locationCheck;
      locationCheck = _path.TowerOnPath(location);

      if(locationCheck)
        _location = location;
      else
        throw new OutOfBoundsException("Tower cannot be placed on path.");
    }

MapLocationCode

class MapLocation : Point
  {
    public MapLocation(int x, int y, Map map) : base(x, y)
    {
        if(!map.OnMap(this))
        {
            throw new OutOfBoundsException(x + "," + y + " is outside the boundaries of the map.");
        }
    }

    public bool InRangeOf(MapLocation location, int range)
    {
      return DistanceTo(location) <= range;
    }
  }

So, if I'm understanding this correctly, my game currently has issue with the fact I've listed my _location as Null, even though its set to equal the location if the Tower does not land on the path. Upon searching through StackOverflow, the site suggests that I might not be using the variable at all, which I find odd, because the only time I wouldn't be using this was when a tower lands on the path which should have been grabbed by my exception.

Am I wrong here, or what am I missing that would cause this error?

Steven Parker
Steven Parker
162,981 Points

It would be easier to observe the issue if you make a snapshot of your workspace and post the link to it here.

3 Answers

Steven Parker
Steven Parker
162,981 Points

It looks like you've added some code that isn't part of the video project. In the constructor for "Tower" I see a call made to _path.TowerOnPath, but the variable "_path" was never initialized. This causes the null reference (not "_location").

Also, the purpose of the "TowerOnPath" is unclear, since the towers are placed next to but never on the path. So even if you give the "Tower" constructor access to the path, the tower placements will generate an exception.

Steven Parker
Steven Parker
162,981 Points

The line "private readonly Path _path;" only declares the variable, it does not initialize it. So it contains the null value.

And "locationCheck" is false when the tower is not on the path, so the "else" part of the conditional would run and that generates the exception.

Christian Fincher
Christian Fincher
3,065 Points

Sorry about that Steven Parker - I've added a snapshot of it here - https://w.trhou.se/duttpu3zl9

Christian Fincher
Christian Fincher
3,065 Points

Don't I initialize it underneath MapLocation?

class Tower
  {
    private readonly MapLocation _location;
    **private readonly Path _path;**
    private const int _range = 1;
    private const int _power = 1;
...

To your second part, that was part of my earlier question during the "challenge" portion of creating a check to see if a Tower would ever me placed on the path. I thought the purpose was clear since the method itself is a bool trying to check whether the path and tower have the same location on the map. If they do, then it throws the exception placed in the constructor, where the tower is created in the first place.

Edit - and I realize now it would probably be better suited not in the constructor but in another method after the tower is created in the game class (or prompted) which would eliminate needing that put in there.

Steven Parker
Steven Parker
162,981 Points

See the comment I added to my answer.