c# - 为什么通用列表索引器显示两种行为
问题描述
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?**
}
为什么覆盖元素副本的整个值会影响列表?我想知道这段代码在后台是如何工作的。
解决方案
在这一行:
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);
推荐阅读
- javascript - 仅当一个对象在 useSelector 中发生更改时如何导致重新渲染
- amazon-web-services - AWS Lambda 读取 Athena 数据库文件并写入 S3 无济于事
- numpy - 使用 Numpy 获取二维数组列表并将非零值作为单个数组中的值
- html -
在每个单词后带有换行符的块,宽度限制为最长的单词
- javascript - 选择下拉值时如何删除下拉列表的重复项
- javascript - 直接从firebase函数临时文件夹下载
- xcode - 禁用 Xcode 实用程序面板自动显示功能
- c# - 在 .net 核心中使用 Signalr 向单个用户和管理员角色用户发送通知
- shader - 在 WebGL 中排序实例
- flutter - 如何使用 Flutter 增加 Firebase 身份验证会话时间?