为什么通用列表索引器显示两种行为
Why does generic list indexer show two behaviors
static void Main(string[] args)
{
var vs = new List<Person> { new Person(1) };
vs[0].IncrementAge();
Console.WriteLine(vs[0].Age); // output: 1
}
struct Person
{
public int Age { get; set; }
public Person(int age) : this()
{
Age = age;
}
public int IncrementAge()
{
Age++;
return Age;
}
}
我明白为什么我们会得到这样的结果。列表索引器 returns 元素的副本。没关系。
我的问题是为什么我们在下面的代码中没有得到相同的结果?因为我更改了元素副本的值:
static void Main(string[] args)
{
var vs = new List<int> { 1 };
vs[0] = 2;
Console.WriteLine(vs[0]); // output: 2, **why not 1?**
}
为什么覆盖元素副本的整个值会影响列表?我想知道这段代码在后台是如何工作的。
这一行:
vs[0].IncrementAge();
您检索 索引 0 处的值,这会创建 struct
的 副本。在副本中,Age
递增,副本然后丢失。它不会保存回列表中。
在此上下文中,vs[0]
被转换为调用一个 getter 方法,该方法 returns 一个值。它将与(伪代码)相同:
vs.get_Item(0).IncrementAge();
相反,这里:
vs[0] = 2;
你将位置 0 的值替换 为新值。这就是它在列表中更改的原因。
在此上下文中,vs[0]
被转换为调用 setter 方法,该方法将提供的值存储到列表的内部数据结构中。它将与(伪代码)相同:
vs.set_Item(0, 2);
数组索引器returns 对数组元素和数组值的引用将被更改,但列表值不会。列表索引器 returns 元素的副本。在此临时对象上调用成员函数。所以,原来的列表成员根本没有改变。
static void Main(string[] args)
{
var vs = new List<Person> { new Person(1) };
vs[0].IncrementAge();
Console.WriteLine(vs[0].Age); // output: 1
}
struct Person
{
public int Age { get; set; }
public Person(int age) : this()
{
Age = age;
}
public int IncrementAge()
{
Age++;
return Age;
}
}
我明白为什么我们会得到这样的结果。列表索引器 returns 元素的副本。没关系。
我的问题是为什么我们在下面的代码中没有得到相同的结果?因为我更改了元素副本的值:
static void Main(string[] args)
{
var vs = new List<int> { 1 };
vs[0] = 2;
Console.WriteLine(vs[0]); // output: 2, **why not 1?**
}
为什么覆盖元素副本的整个值会影响列表?我想知道这段代码在后台是如何工作的。
这一行:
vs[0].IncrementAge();
您检索 索引 0 处的值,这会创建 struct
的 副本。在副本中,Age
递增,副本然后丢失。它不会保存回列表中。
在此上下文中,vs[0]
被转换为调用一个 getter 方法,该方法 returns 一个值。它将与(伪代码)相同:
vs.get_Item(0).IncrementAge();
相反,这里:
vs[0] = 2;
你将位置 0 的值替换 为新值。这就是它在列表中更改的原因。
在此上下文中,vs[0]
被转换为调用 setter 方法,该方法将提供的值存储到列表的内部数据结构中。它将与(伪代码)相同:
vs.set_Item(0, 2);
数组索引器returns 对数组元素和数组值的引用将被更改,但列表值不会。列表索引器 returns 元素的副本。在此临时对象上调用成员函数。所以,原来的列表成员根本没有改变。