提问人:Vrt 提问时间:3/26/2021 更新时间:3/27/2021 访问量:1012
为什么或如何 Vector2/Vector3 结构是不可变的?
Why or How is a Vector2/Vector3-struct immutable?
问:
对于我的网格系统(2D数组),我正在创建一个-struct。这与 .Index2
Vector2
遇到一些问题,我阅读了结构。遇到可变和不可变的主题。
长话短说,可变结构很糟糕。所以后来我想知道,我如何让我的结构不可变?这让我想到了这篇文章。
如果理解正确,要使结构不可变,您必须确保在创建实例后,无法修改实例的成员。
但是当我看到统一的 -struct 时。创建 后,可以修改其值:Vector2
new Vector2(0f, 0f)
Vector2 myVector = new Vector2(1f, 1f);
myVector.x = 2f;
这很好用。
与 -method 相同:.Set
Vector2 myVector = new Vector2(1f, 1f);
myVector.Set(2f, 2f);
还查看了 a 的定义,我没有看到上面链接的帖子中建议的任何解决方案。Vector
这让我想知道几件事?
- a 是不可变的结构吗?
Vector2
- 如果是,它是如何构建的,使其在能够修改成员的同时仍然不可变?
- 如果不是,为什么它仍然是一个安全的结构?
答:
- 不,它是可变的
- 事实并非如此
- 事实并非如此;可变结构可能导致问题的所有方式都非常适用;所以:小心点
评论
答案 1:不,它不是一成不变的;我想你自己证明了这一点
答案 2:很确定你的问题是一个矛盾;不能修改不可变的对象
回答 3:如果你有想要创建的东西,那么不可变的对象是很好的,一次又一次地使用而不改变,然后你就完成了。如果要创建、使用、更改、再次使用、再次更改等,则它们不适用。如果你有一个场景,事情是创建/使用但不做更改/完成的,那么让它不可变是一件好事,因为你知道它没有被在你背后编辑......它可以像代码中的岩石一样被依赖。这不适合您想要/需要改变的东西(例如,滚动球的位置)。因此,Vector2 是最后一种情况的理想选择。这并不是关于安全和不安全,而是关于适当和不适当的
评论
Vector2
不是“对象”(除非你把它装箱),所以“不可变对象”可能是一个错误的比较;在谈论仓位时——我会说,当你改变仓位时,从逻辑上讲,你不会改变仓位的特征,而是:你把整个仓位改成不同的仓位值——仓位值由 x/y/z(或其他什么)组成的事实是无关紧要的;我会反驳说,不可变的值类型非常适合“位置”类型,只是:你会做什么或其他什么obj.Position = obj.Position.Add(3, 0, 42);
它不是一成不变的。大多数人都遇到过无法修改 Vector3 的单个组件的问题,例如
transform.position.x=value;
这是行不通的,但不是出于不变性的原因。这是行不通的,因为transform.position实际上不是一个字段,而是一个属性(getter setter pair)。在 Unity3D 公开的几乎没有任何东西是 setter/getter 的,所以它的定义不是
公共 Vector3 位置;
但是由于三个独立的元素、一个支持字段和一个 parir 方法运行来检索或设置值,所以(我称我的属性 pos not position 不要与实际的 Transform implementatoin wchich 混淆更复杂)。
private Vector3 _pos;
public Vector3 pos { get { return _pos;} set { _pos=value;}}
现在诀窍来了。属性本质上只是 C# 中的语法糖,因此在后台编译为类似
private Vector3 _pos;
public Vector3 GetPos ()
{ return _pos; }
public void SetPos(Vector3 value)
{ _pos=value;}}
现在,如果您仔细观察诸如
transform.position.x+=1; // won't work
它们没有意义,因为你实际上的意思是:
Vector3 temp = transform.GetPos();
temp.x+=1; // Vectors3 mutate all right
transform.SetPos(temp);
因为 .position 是一个属性,并且有一个 backing 方法,所以它必须执行并返回一个完整的结构,然后才能修改和发送新的结构。如果位置是一个字段,这很好,但转换将无法知道它已更改并应用您的更改(如果您设置全局位置,它确实需要做大量的数学运算)
评论
Vector2
transform.position.x = ...