C# 值类型列表
C# Value Type Lists
我有点困惑。结构或多或少是在堆栈上构建的值类型,因此具有简单的生命周期。
使用结构体构建列表时,不能直接修改它们,因为返回值是一个副本,不会真正修改存储在列表中的项。
我的困惑来了:为什么我不能直接更改列表中的结构项,但我可以直接访问和修改基值类型(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;
^ ^
| |
是问题所在。
我有点困惑。结构或多或少是在堆栈上构建的值类型,因此具有简单的生命周期。
使用结构体构建列表时,不能直接修改它们,因为返回值是一个副本,不会真正修改存储在列表中的项。
我的困惑来了:为什么我不能直接更改列表中的结构项,但我可以直接访问和修改基值类型(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;
^ ^
| |
是问题所在。