事情是这样的。
你说了这句话:
“我想留下 Foo 的结构。我该怎么做?foos [0] = tempFoo?只是为了一个赋值有点复杂?!”
没错,就是这样。你需要的是一种
赋值,而不是一种
修改。值类型(结构体)通常应该被视为
值。
以
int
为例。如果你有一个名为
ints
的
List<int>
,你会如何更改
ints [0]
的值?
大概是这样吧?
ints[0] = 5
注意,没有办法做到像这样的事情:
ints[0].ChangeTo(5)
这是因为
Int32
是一个不可变的结构体。它被设计成作为一个
值来处理,不能被改变(所以一个
int
变量只能被赋值给一个新的值)。
你的
Foo
结构体是一个令人困惑的情况,因为它可以被改变。但由于它是一个值类型,只有副本被传递(与我们在日常生活中处理的所有值类型一样,如
int
、
double
、
DateTime
等)。因此,除非它被通过引用传递给你(使用方法调用中的
ref
关键字),否则你不能从远处改变实例。
因此,简单的答案是,是的,要改变
List<Foo>
中的
Foo
,你需要将其赋值给一个新的值。但你真的不应该有一个可变的结构体。
免责声明:与几乎所有您可能获得的建议一样,在任何事情上,这都不是100%的硬性规定。非常有技巧的开发人员Rico Mariani为了好的原因编写了可变的Point3d结构体,他在博客上解释了这些原因。但这是一个非常知识渊博的开发人员知道他正在做什么的例子;通常作为编写值类型与引用类型的标准方法,应该使值类型成为不可变的。
针对你的评论:当你处理一个可变结构体,比如
Point
时,基本上你需要像这样做:
Point p = points[0];
p.Offset(0, 5);
points[0] = p;
或者,另外一种选择是:
Point p = points[0];
points[0] = new Point(p.X, p.Y + 5);
这句话的英文原意是:“我不会做...的原因是...”。
points[0] = new Point(points[0].X, points[0].Y + 5);
“…这里你复制了
points[0]
的值
两次。要记住,通过索引访问
this
属性基本上是一个方法调用。所以这段代码实际上是在执行这个操作:”
points.set_Item(0, new Point(points.get_Item(0).X, points.get_Item(0).Y + 5);
请注意过多地调用
get_Item
(没有充分的理由而进行额外复制)。