为什么我不能将自动实现的 getter 和 setter 与列表一起使用? (统一,C#)

Why can't I use automatically implemented getters and setters with a List? (Unity, C#)

我正在尝试更好地了解 getter 和 setter。

我知道我可以使用自动实现的 getter 和 setter,例如 public Vector3 Position { get; set; } as shorthand for

private Vector3 _position;
public Vector3 Position
{ 
    get {return _position;} 
    set{_position = value;} 
}

但我不明白为什么这对列表不起作用。如果我尝试声明一个列表,如:

List<Vector3> Positions { get; set;}

Unity 向我抛出空引用异常。

但是如果我使用长格式:

private List<Vector3> _position = new List<Vector3>();
public List<Vector3> Position
{ 
    get {return _position;} 
    set{_position = value;} 
}

它工作得很好。我认为这与声明列表的方式有关,但我想知道这里到底发生了什么。

当你写这篇文章时

List<Vector3> Positions { get; set;}

你声明了一个 List<Vector3> 类型的 属性,但是你没有给它分配任何东西,所以试图取消引用它,例如

Positions.Add(vec3);

将抛出 NullReferenceException。您可以继续使用自动属性并初始化您的列表,如:

List<Vector3> Positions { get; set;} = new List<Vector3>();

C# 有值类型和引用类型的概念。值类型“像整数一样”——值类型的变量实际上存储值,并且它有一个默认值(通常是某种零)。

另一方面,引用类型是对内存中某物的引用,引用类型的变量不存储实际对象,而是存储实际对象的地址。如果你还没有初始化它,引用类型变量默认为零,a.k.a。空。

Vector3 是值类型。列表是引用类型。这解释了不同的行为,以及为什么您的第二个 List 示例有效 - 在这种情况下,您已经明确创建并初始化了列表对象并将您的引用指向它。

这也是为什么一般来说,在列表 属性 上使用 set 方法不是一个好主意。你不想让外部调用者完全改变它指向的列表,你想改变你已经拥有的实际列表的内容。