为何修改List<int>可行,修改List<ValueTuple>却报CS1612错误?
为什么List可直接修改元素,List却不行?
核心原因:值类型的操作逻辑差异
首先明确:int 和 ValueTuple 都是值类型,但两者的修改操作本质存在差异:
1. List 的修改逻辑
你写的 test[i] += 1 是编译器语法糖,展开后等价于:
test[i] = test[i] + 1;
这个过程分三步执行:
- 通过索引器的
get方法,取出列表对应位置的int值副本; - 计算副本加1后的新值;
- 通过索引器的
set方法,把新值存回列表的内部数组。
整个操作触发了索引器的读写流程,最终真正修改了列表里的原位置元素。
2. List<(int,int)> 的报错原因
test2[i].Item1 += 1 的操作逻辑是:
- 通过索引器的
get方法,取出对应位置的ValueTuple副本; - 试图修改这个临时副本的Item1属性;
但这个临时副本不会被赋值回列表,修改操作完全无意义——副本会在语句结束后被丢弃,原列表的元素根本不会发生变化。
C# 编译器会直接阻止这种无效操作,因此抛出 CS1612 错误:“无法修改List<(int, int)>.this[int]的返回值,因为它不是变量”。
解决办法:修改副本后赋值回列表
要修改ValueTuple的成员,必须先取出整个元组实例,修改后再赋值回列表的对应位置:
var test2 = new List<(int, int)>() { (1, 2), (2, 3), (3, 4) }; for(int i = 0; i < test2.Count; i++) { var tempTuple = test2[i]; tempTuple.Item1 += 1; test2[i] = tempTuple; // 将修改后的副本存回列表 }
这样就能完成对原列表元组成员的修改。
总结
所有值类型从List
- 对于int这类简单值类型,
+=操作隐含了“计算新值并赋值回”的逻辑,最终修改了原列表; - 对于ValueTuple这类复杂值类型,直接修改返回副本的成员是无效操作,必须显式取出副本、修改、再赋值回列表。
内容的提问来源于stack exchange,提问作者William
相关产品推荐
相关产品推荐

