C# 中的浅拷贝和深拷贝

2024 年 8 月 29 日 | 4 分钟阅读

在许多编程语言中,例如 Java 或 C#,当我们把一个对象变量赋值给另一个对象变量时,我们复制的是对象在内存中的位置引用,而不是对象本身。因此,这两个变量都指向内存中同一个对象实例。这与像 int、bool 等值类型变量形成对比,值类型变量直接包含实际值。

例如

在这里,g1g2 是引用变量,它们存储指向内存中实际 MyClass 对象的引用(内存地址),比如地址 5000。当我们用 = 将 g1 赋值给 g2 时,我们复制的是引用,所以现在 g1 和 g2 指针都指向地址 5000 处的 SAME MyClass 实例。

因此,通过 g1 或 g2 对对象所做的任何更改都将通过两者访问对象时可见,因为实际对象仍然只有一个。这与复制像 int 这样的值类型不同,在值类型中,g2 将存储其独立的值副本。

总而言之,= 赋值运算符与引用类型一起使用时,复制的是引用,而不是实际对象,导致两个引用都指向同一个实例。值类型直接包含值,因此赋值将值复制到新变量中。

什么是浅拷贝?

对象的浅拷贝不会创建嵌套对象的新副本,而是复制对嵌套对象的引用。这意味着被复制的对象指向与原始对象相同的嵌套对象。

更详细地

  • 当进行浅拷贝时,会创建一个新实例,其中包含与原始对象中存在的精确值副本。
  • 原始对象中列表、数组和其他引用类型字段的引用被复制到新对象。因此,新对象指向相同的嵌套对象。
  • 如果原始对象被修改,则嵌套对象也会被修改。由于浅拷贝指向相同的嵌套对象,这些更改也会反映在副本中。
  • 本质上,嵌套对象是通过引用在原始对象和浅拷贝对象之间**“共享”**的,而不是被复制。只复制顶层值。

示例

让我们看一个 C# 程序来演示**浅拷贝**概念。

输出

Original: Person: Jane, Age: 25, Hobbies: Reading, Gaming, Traveling
Copy: Person: John, Age: 30, Hobbies: Reading, Gaming, Traveling

什么是深拷贝?

**深拷贝**是一种对象拷贝,它完全复制原始对象中所有级别的嵌套对象。这意味着它不是复制嵌套对象的对象引用,而是创建这些嵌套对象的新实例。

更详细地

  • 创建深拷贝时,会递归地通过对象中所有级别的嵌套创建完全新的嵌套对象实例。
  • 原始对象和深拷贝对象之间不共享任何对象引用。它使复制的对象与复制后对原始对象所做的任何更改隔离开来。
  • 与浅拷贝相比,执行深拷贝需要额外的处理/内存来创建重复的嵌套对象。这使得原始对象和复制对象之间实现了真正的独立性。
  • 语言可以通过复制构造函数、克隆方法等提供深拷贝的内置支持。另外,手动深拷贝需要递归遍历对象结构以创建副本。

示例

让我们看一个 C# 程序来演示深拷贝概念。

输出

Original: Person: Virat, Age: 25
Copy: Person: Virat, Age: 30