1

I have created a custom struct and a class. The structs are points in 3D Space:

public struct Point3D
{
    //fields
    private static Point3D center = new Point3D(0,0,0);

    //properties
    public int X { get; set; }
    public int Y { get; set; }
    public int Z { get; set; }
    public static Point3D Center { get { return center; } }

    //constructors
    public Point3D(int x, int y, int z) : this()
    {
        this.X = x;
        this.Y = y;
        this.Z = z;
    }

    public override string ToString() { return string.Format("({0}; {1}; {2})", this.X, this.Y, this.Z); }
}

and the custom class is path which is supposed to store the points:

public class Path
{
    private List<Point3D> storedPoints = new List<Point3D>();

    public List<Point3D> StoredPoints { get; set; }

    public void AddPoint(Point3D point) { this.StoredPoints.Add(point); }

    public void DeletePointAt(int index) { this.StoredPoints.RemoveAt(index); }

    public void ClearPath() { this.StoredPoints.Clear(); }

    public override string ToString()
    {
        StringBuilder sb = new StringBuilder();
        foreach (var item in this.StoredPoints)
        {
            sb.Append(item);
            sb.Append(System.Environment.NewLine);
        }
        return sb.ToString();
    }
}

I have not created a constructor for the path class as I will always want to have an instance with an empty list List\ in it. However, when I run the program, I get NullReferenceException. This is the code of the main method:

    static void Main(string[] args)
    {
        Point3D point1 = new Point3D(-2, -4, -10);
        Point3D point2 = new Point3D(6, 7, 8);
        Path path1 = new Path();
        path1.AddPoint(point1);
        path1.AddPoint(point2);
        path1.AddPoint(new Point3D(2, 4, 6));
        path1.AddPoint(new Point3D(-9, 12, 6));
        Console.WriteLine(path1);
    }

I get the error when I try to add the first point. In the debugger I see that the Path object has the value null before adding the first point, but how do I overcome this problem without having to write a constructor, taking as a parameter at least one point, that is, create an empty path.

1
  • Thanks to all of you. Just one sub-question. What if I remove the private field List<Point3D> storedPoints altogether and just leave the auto-property public List<Point3D> StoredPoints { get; set; }? Why is that not working? Commented Jun 6, 2013 at 14:11

3 Answers 3

1

Your StoredPoints property is alone and not initialized. Your intention is probably that it will get/set your private storedPoints field. Modify the get/set functions for StoredPoints to get/set your private field and you'll solve your problem.

public List<Point3D> StoredPoints 
{ 
  get
  {
    return storedPoints;
  }
}

Edit:

If you eliminate the storedPoints field, and still don't want a constructor, you can do the following:

public void AddPoint(Point3D point) 
{ 
  if (this.StoredPoints == null)
    this.StoredPoints = new List<Point3D>();
  this.StoredPoints.Add(point); 
}

This is called lazy initialization. However, the above implementation is not thread-safe. If you're guaranteed to be single-threaded, then it should be fine. You may want to put similar initialization in other modifiers of StoredPoints. You'll also need to check StoredPoints for null whenever accessing it directly from outside the class.

Edit:

I have not created a constructor for the path class as I will always want to have an instance with an empty list List\ in it.

One has nothing to do with the other. You can have a constructor and not initialize your list.

Something else to keep in mind: does having a null StoredPoints property actually mean anything different than an empty StoredPoints property? If not, then be safe and initialize StoredPoints to an empty list.

Sign up to request clarification or add additional context in comments.

3 Comments

Regarding thread-safety, the very type List<T> is not thread-safe either, so even if he initialized it in a constructor, things would still break down in a multi-threaded scenario (where he should change to a collection from System.Collections.Concurrent).
Thank you both for the perfect explanation. The part I still don't get is why I have to initialize it,if I initialize it to an empty list, which by default has a value of null. In both cases it has a value of null, but in the second case it is explicitly initialized? But I guess this is something I need to further work on as I am a newbie.
By default, your property will have value null. If you initialize it using new List<Point3D>(), it will not be null, instead it will be an valid list that is empty. Don't get confused between "no list" (which is null) and "empty list" (which is a list that exists, but is empty).
1

You have two members storedPoints and StoredPoints that are not related!

You should write out the getter of StoredPoints explicitly and let it return storedPoints.

(Also, the struct you created is a mutable struct. That is considered dangerous by many.)

1 Comment

Because it's default value will be null. You'll have to initialize it somewhere (usually in a constructor).
1
public List<Point3D> StoredPoints { get; set; }

When you are calling AddPoints, you are trying to access a property that has not been initialized. Before you use the StoredPoints property, you must do

StoredPoints = new List<Point3D>();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.