简体   繁体   中英

NullReferenceException when trying to populate an empty instance of a custom class with a struct

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.

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.)

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.

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>();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM