You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何在列表中迭代C#结构体时无法修改其属性?

为什么遍历结构体列表时无法修改属性?

这个问题的核心其实和C#里**值类型(Value Type)**的特性直接相关,咱们一步步把它说清楚:

先搞懂结构体的本质:值类型的拷贝特性

C#里的结构体是值类型,和类(引用类型)最大的区别就是:值类型在赋值、传递或者从集合中获取时,会创建整个实例的副本,而不是像引用类型那样只传递内存地址。这个特性是所有问题的根源。

为什么foreach循环里改不了?

在你的foreach代码里:

foreach(var l in list) { 
    l.Prop = 20; // 编译错误
}

这里的l是列表中对应结构体元素的副本,而且C#编译器特意把这个迭代变量设为了只读状态——就算不设只读,你修改l的属性也只是改了这个副本,原列表里的结构体元素完全不会受到影响,属于无效操作。编译器干脆直接禁止这种无意义的代码,就抛出了那个“Cannot modify members of 'l' because it is a 'foreach iteration variable'"的错误。

为什么for循环里也改不了?

你可能以为换成for循环就能绕过去,但其实问题本质没变:

for (int i=0; i<list.Count(); ++i) 
    list[i].Prop = 20; // 还是编译错误

这里的list[i]调用的是List<T>的索引器,它返回的依然是结构体的临时副本。你修改这个副本的Prop属性后,这个副本马上就会被丢弃,原列表里的结构体元素根本没被改动。编译器同样能识别出这种无效操作,所以也会报错。

那怎么才能正确修改呢?

要解决这个问题,你需要手动完成“取出副本→修改副本→把修改后的副本放回列表”的流程:

for (int i = 0; i < list.Count; ++i) 
{
    var temp = list[i]; // 取出列表中结构体的副本
    temp.Prop = 20;     // 修改副本的属性
    list[i] = temp;     // 将修改后的副本重新放回列表,替换原元素
}

这样操作后,列表里的结构体元素才会真正被更新。

补充:如果是类(引用类型)就不会有这个问题

如果把A改成类而不是结构体,不管是foreach还是for循环,修改属性都不会报错——因为列表里存的是类实例的引用,你操作的是引用指向的原实例,而不是副本。

内容的提问来源于stack exchange,提问作者Grigoryants Artem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:47:46