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

如何通过变量修改List中的对象?C#引用赋值问题问询

问题分析与解决方案

首先咱们得搞明白为什么你的代码执行后输出false——这是C#引用类型变量的工作逻辑导致的:

当你执行Foo f = list[0];时,变量f和list[0]都指向同一个对象实例f1,但它们是两个独立的引用变量。当你给f赋值f2时,只是把f的指向改成了f2,但list[0]的指向依然是f1,所以最后比较自然是false。

你完全不需要用指针来实现“通过修改f改变list[0]”的需求,C#有更安全、更符合托管代码风格的方式,下面分场景给你方案:

场景1:修改对象的成员(而非替换整个对象)

如果你的目标是修改list[0]指向对象的属性/字段,而非把它换成另一个对象,那直接操作f的成员就可以了——因为f和list[0]指向同一个实例:

public class Foo
{
    public string Name { get; set; }
}

// 测试代码
Foo f1 = new Foo { Name = "Old" };
Foo f2 = new Foo { Name = "New" };
List<Foo> list = new List<Foo>() { f1 };

Foo f = list[0];
f.Name = f2.Name; // 修改f指向对象的成员

Console.WriteLine(list[0].Name); // 输出"New",list[0]的对象已被修改

场景2:替换list[0]指向的整个对象

如果你确实需要把list[0]换成f2,可以用以下两种优雅的方式:

方式1:使用引用参数(ref)

写一个接收ref参数的方法,通过它直接修改列表元素的引用:

void ReplaceFoo(ref Foo target, Foo newInstance)
{
    target = newInstance;
}

// 调用方法替换list[0]
ReplaceFoo(ref list[0], f2);
Console.WriteLine(list[0] == f2); // 输出true

方式2:使用包装类

把Foo实例包装在一个容器类里,列表存储容器的引用,修改容器内的值就会同步到列表中:

public class Wrapper<T>
{
    public T Value { get; set; }
}

// 测试代码
Wrapper<Foo> w1 = new Wrapper<Foo> { Value = f1 };
Wrapper<Foo> w2 = new Wrapper<Foo> { Value = f2 };
List<Wrapper<Foo>> list = new List<Wrapper<Foo>> { w1 };

Wrapper<Foo> w = list[0];
w.Value = f2; // 修改包装类的Value属性

Console.WriteLine(list[0].Value == f2); // 输出true

关于指针的选项(不推荐)

虽然C#支持unsafe代码和指针,但这是非常不推荐的方式——它违背了C#的托管内存安全模型,需要开启项目的unsafe编译选项,还容易引发内存问题。如果非要用指针,代码大概是这样:

unsafe
{
    Foo f1 = new Foo();
    Foo f2 = new Foo();
    List<Foo> list = new List<Foo>() { f1 };
    
    fixed (Foo* ptr = &list[0])
    {
        *ptr = f2; // 通过指针直接修改列表元素的引用
    }
    
    Console.WriteLine(list[0] == f2); // 输出true
}

但再次强调:除非你在做极端性能优化的底层场景,否则完全没必要用这种方式,优先选择前面的安全方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:46:30