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

类对象与字符串变量的浅拷贝行为差异原因探究

字符串与自定义类引用类型行为差异的核心原因

首先看第一个字符串操作的示例:

string a = "John";
string b = "Doe";

a = b; // 浅拷贝字符串
b = "Elon Musk";

Console.WriteLine(a); // 输出: Doe

上述代码输出为“Doe”,说明修改变量b不会影响a。

再看自定义类对象的操作示例:

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

// ----

Person person1 = new Person { Name = "John" };
Person person2 = person1; // 浅拷贝

Console.WriteLine(person1.Name); // 输出: John
Console.WriteLine(person2.Name); // 输出: John

person2.Name = "Jane"; // 通过person2修改属性

Console.WriteLine(person1.Name); // 输出: Jane (变化同步到person1)
Console.WriteLine(person2.Name); // 输出: Jane

这里修改person2的属性后,person1的属性也同步变化,和字符串场景的表现完全不同。

问题

我想理解为何两种场景下表现存在差异:类对象与string类型均为引用类型,按道理第一种场景也应出现修改同步的情况?请解释导致这种差异的核心原因。我知道string类型是不可变的,类对象是可变的吗?这是引发差异的关键因素吗?


核心解释

1. 两种场景的操作本质完全不同

  • 字符串场景:a = b是让变量a指向b当前引用的字符串对象(即"Doe")。后续b = "Elon Musk"并没有修改原有"Doe"对象的内容,而是让b重新指向了一个全新的字符串对象("Elon Musk")。此时a仍然指向原来的"Doe",所以两者互不影响。
  • 自定义类场景:person2 = person1是让person2和person1指向同一个Person对象。后续person2.Name = "Jane"并没有改变person2的引用指向,而是直接修改了这个共享对象内部的Name属性值,所以person1因为指向同一个对象,自然能看到这个修改。

2. string的不可变性是关键前提

string是.NET中的不可变引用类型:一旦字符串对象被创建,它的内容就永远无法被修改。所有看似修改字符串的操作(赋值、拼接、替换等),本质都是创建新的字符串对象,并让变量指向这个新对象。
而你定义的Person类是可变引用类型:它的内部属性可以被修改,不需要创建新的Person对象就能改变其状态。

3. 差异的本质总结

两种场景的核心区别不在于“是否是引用类型”,而在于你执行的操作是改变变量的引用指向,还是修改引用指向的对象内部状态:

  • 字符串场景中,你只能做前者(改变引用),因为字符串不可变,根本无法修改原有对象的内容;
  • 自定义类场景中,你做的是后者(修改对象内部状态),因为类对象可变,且你没有改变变量的引用指向。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 13:26:29