自定义结构体与内置结构体(如Int32)在List<T>和Array中的值引用差异
List与数组索引器的差异解析
先明确核心差异:
- 数组的索引器返回的是元素的引用(ref),直接指向内存中实际存储的元素
- List
的索引器返回的是值类型的副本,是一个临时变量
1. 为什么numbers[0]++可以正常运行?
int是值类型,但++运算符本质是"读取值→修改→写回"的复合操作。numbers[0]++等价于:
int temp = numbers[0]; // 取List中元素的副本 temp++; // 修改副本 numbers[0] = temp; // 将修改后的副本写回List
虽然List索引器返回的是副本,但我们通过赋值操作把修改后的结果同步回了List,所以编译器允许这种操作。
2. 为什么mutablesList[0].X++会报错?
当你访问mutablesList[0]时,得到的是自定义结构体Mutable的临时副本。你修改这个副本的X字段,只是修改了一个马上会被回收的临时变量,原List中的结构体完全没变化。编译器直接拦截这种无意义的操作,避免你写出无效代码。
3. 数组的两种情况为什么都合法?
数组的索引器返回的是ref T,也就是直接指向数组内存中的实际元素:
mutablesArray[0].X++:直接修改数组里存储的那个Mutable结构体的X字段numbers[0]++:直接修改数组里的int值,不需要额外的赋值步骤
对应代码验证
List<int> numbers = new List<int> { 1 }; List<Mutable> mutablesList = new List<Mutable> { new Mutable { X = 1 } }; Mutable[] mutablesArray = new Mutable[] { new Mutable { X = 1 } }; numbers[0]++; // 正常:读取→修改→写回 mutablesArray[0].X++; // 正常:直接修改数组内的结构体字段 // mutablesList[0].X++; // 编译错误:修改临时副本的字段无意义
内容的提问来源于stack exchange,提问作者Mehmet Ali Duran
相关产品推荐
相关产品推荐

