尝试使用struct填充自定义类的空实例时出现NullReferenceException

时间:2013-06-06 14:01:52

标签: c# .net class struct nullreferenceexception

我创建了一个自定义结构和一个类。结构是3D空间中的点:

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

,自定义类是应该存储点的路径:

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

我没有为路径类创建构造函数,因为我总是希望在其中有一个带有空列表List \的实例。但是,当我运行程序时,我得到NullReferenceException。这是主要方法的代码:

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

当我尝试添加第一个点时,我收到错误。在调试器中,我看到Path对象在添加第一个点之前的值为null,但是如何在不必编写构造函数的情况下克服此问题,将至少一个参数作为参数,即创建一个空路径。

3 个答案:

答案 0 :(得分:1)

您有两个与storedPointsStoredPoints无关的成员!

您应该明确写出StoredPoints的getter并让它返回storedPoints

(另外,你创建的结构是一个可变的结构。许多人认为这很危险。)

答案 1 :(得分:1)

您的StoredPoints属性是独一无二的,未初始化。您的意图可能是它将获取/设置您的私人storedPoints字段。修改StoredPoints的获取/设置功能以获取/设置您的私人字段,您将解决您的问题。

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

修改

如果删除了storedPoints字段,但仍然不想使用构造函数,则可以执行以下操作:

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

这称为延迟初始化。但是,上述实现不是线程安全的。如果您保证是单线程的,那么应该没问题。您可能希望在StoredPoints的其他修饰符中添加类似的初始化。每当直接从课外访问时,您还需要检查StoredPoints是否为null。

修改

  

我没有为路径类创建构造函数,因为我总是希望在其中有一个带有空列表List \的实例。

一个与另一个无关。您可以拥有构造函数而不是初始化列表。

要记住的其他事项:确实有一个null StoredPoints属性实际上意味着什么不同于一个空的StoredPoints属性?如果没有,那么请安全并将StoredPoints初始化为空列表。

答案 2 :(得分:1)

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

当您呼叫AddPoints时,您正在尝试访问尚未初始化的属性。在使用StoredPoints属性之前,必须执行

StoredPoints = new List<Point3D>();