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

为何List<string>元素无法更新,而List<ComplexObject>可以?

为什么List与List<自定义类>的ForEach更新行为存在差异?

场景回顾

场景1:List更新失败

List<string> source = new List<string>();
source.Add("one");
source.Add("two");
source.Add("three");

// 执行后集合元素无变化
source.ForEach(x => { if (x == "two") { x = "twenty"; } });

场景2:List更新成功

先补充自定义类的定义:

public class ComplexObject
{
    public int Key { get; set; }
    public string DisplayText { get; set; }
}

初始化集合并更新:

List<ComplexObject> obj = new List<ComplexObject>
{
    new ComplexObject { Key = 1, DisplayText = "One" },
    new ComplexObject { Key = 2, DisplayText = "two" }
};

// 执行后Key=2的元素DisplayText成功更新
obj.ForEach(x => { if (x.Key == 2) { x.DisplayText = "Update value for 2"; } });

核心原因:C#的参数传递规则 + 类型特性

这本质是值传递机制,结合string的不可变性和引用类型的特性共同导致的:

  1. 参数传递默认是值传递
    ForEach的委托参数x,是集合中元素的副本:

    • 如果是值类型(如int、struct),副本是数据本身;
    • 如果是引用类型(如自定义类、string),副本是对象的内存引用地址。
  2. string的特殊性:不可变的引用类型
    string虽然是引用类型,但它是不可修改的——任何对string的"修改"操作,都会创建一个新的string对象,而非修改原对象内容。
    在场景1中,x = "twenty"只是把局部变量x的引用指向了新的"twenty"对象,但List中存储的原引用还是指向旧的"two"对象,所以集合没有变化。

  3. 自定义类的引用类型特性
    自定义类是普通引用类型,当你拿到x(原对象引用的副本)时,它和List中存储的引用指向同一个对象实例。修改x.DisplayText,本质是通过引用修改了目标对象的属性值,原对象的内容被改变,因此List中的元素自然会体现出这个变化。


总结

  • 场景1:修改的是局部变量x的引用,和List中存储的原引用无关,且string不可变无法修改原对象内容;
  • 场景2:修改的是引用指向的对象的属性,原对象被修改,List中的元素(对象引用)指向的内容同步变化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 21:45:28