我有点困惑。结构或多或少是在堆栈上构造的值类型,因此具有简单的生命周期。
当使用结构体构建列表时,您不能直接修改它们,因为返回的值是一个副本,并且不会实际修改存储在列表中的项目。
我的困惑来了:为什么我不能直接更改列表中的结构体项,但我可以直接访问和修改基本值类型(int、float 等...)?
这有效:
List<int> foobar1 = new List<int>();
foobar1.Add(1);
foobar1[0] = 2;
这不是:
public struct foo
{
public int bar;
}
...
List<foo> foobar2 = new List<foo>();
foobar2.Add(new foo());
foobar2[0].bar = 2;
最佳答案
两者本质上是不同的,不仅仅是因为有人认为它是不同的,让我解释一下。
第一段代码批量替换了列表中第 0 个元素位置的 int
值。哪个 int
值并不重要,之后列表会在第 0 个位置包含 int
值 2
。
但是,第二段代码尝试替换结构的部分。是的,我知道,该结构只有一个字段,但编译器没有做出这样的区分。您正在有效地修改从列表中检索的结构的副本。这是不允许的。
所以第一段代码只是将一个新的值类型填充到列表中,第二段代码尝试修改列表中的值类型,这是一个副本。
那么,你能否将第二段代码更改为与第一段相同,即。完全替换列表中的元素?
当然:
var temp = foobar[0];
temp.bar = 2;
foobar2[0] = temp; // no longer modifies the copy, but replaces the element
基本上,就在这里:
foobar2[0].bar = 2;
^ ^
| |
这就是问题所在。
关于C# 值类型列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34570274/