首页 > 解决方案 > 为什么通用列表索引器显示两种行为

问题描述

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;
   }
}

我明白为什么我们会得到这样的结果。列表索引器返回元素的副本。好的,可以。

我的问题是为什么我们在下面的代码中没有得到相同的结果?因为我更改了元素副本的值:

static void Main(string[] args)
{

   var vs = new List<int> { 1 };
   vs[0] = 2;

   Console.WriteLine(vs[0]);     // output: 2, **why not 1?**
}

为什么覆盖元素副本的整个值会影响列表?我想知道这段代码在后台是如何工作的。

标签: c#genericsstructindexer

解决方案


在这一行:

vs[0].IncrementAge();

检索索引 0的值,这会创建struct. 在副本中,Age增加,然后副本丢失。它不会保存回列表中。

在这种情况下,vs[0]转换为调用返回值的 getter 方法。它与(伪代码)相同:

vs.get_Item(0).IncrementAge();

相反,这里:

vs[0] = 2;

您将位置 0 处的值替换为新值。这就是它在 list 中更改的原因。

在这种情况下,vs[0]被转换为调用 setter 方法,该方法将提供的值存储到列表的内部数据结构中。它与(伪代码)相同:

vs.set_Item(0, 2);

推荐阅读