浅拷贝仅复制值类型字段和引用类型地址,深拷贝递归复制所有层级;MemberwiseClone是内置浅拷贝方法,JSON序列化是推荐的深拷贝方式,ICloneable接口不区分深浅且已不推荐使用。

在 C# 中,浅拷贝(Shallow Copy)只复制对象的值类型字段和引用类型的地址(即新旧对象共享同一引用对象),而深拷贝(Deep Copy)会递归复制所有层级的对象,确保新对象与原对象完全独立。实现方式有多种,ICloneable 接口是传统方法之一,但需注意它本身不区分深浅,具体行为由你实现决定。
浅拷贝:MemberwiseClone 是最直接的方式
Object.MemberwiseClone() 是 .NET 提供的内置浅拷贝方法,它创建一个新对象,并将当前对象的字段值逐个复制过去。值类型被复制值,引用类型被复制引用(地址)。
- 只能在类内部调用(因为是
protected方法) - 无需实现接口,开销小,适合简单结构
- 若类中包含数组、集合或自定义引用类型,它们不会被重新创建,新旧对象仍指向同一实例
示例:
class Person { public string Name; public Address Addr; }class Address { public string City; }
var p1 = new Person { Name = "Alice", Addr = new Address { City = "Beijing" } };
var p2 = (Person)p1.MemberwiseClone(); // 浅拷贝
p2.Addr.City = "Shanghai"; // p1.Addr.City 也会变成 "Shanghai"
深拷贝:推荐使用序列化或手动克隆
没有通用的“一键深拷贝”机制,常见可靠方式有:
-
JSON 序列化(推荐用于简单 POCO 类):用
System.Text.Json或Newtonsoft.Json序列化再反序列化,天然实现深拷贝(前提是类型可序列化且无循环引用) -
二进制序列化(已过时,不建议新项目使用):依赖
[Serializable],且类型必须标记为可序列化,.NET Core/.NET 5+ 中默认禁用 - 手动实现 Clone 方法:对每个引用字段显式 new 并复制,控制力最强,适合复杂逻辑或性能敏感场景
JSON 示例(.NET Core 3.0+):
var json = JsonSerializer.Serialize(p1);var p2 = JsonSerializer.Deserialize
ICloneable 接口:语义约定,不是语法保障
ICloneable 只定义了一个 Clone() 方法,它不指定是深还是浅——这是开发者责任。很多老代码或文档里把它等同于“浅拷贝”,但实际应以文档或实现为准。
- 实现时需明确注释说明是深还是浅,否则极易引发 bug
- 返回类型是
object,调用方需强制转换,不够类型安全 - .NET 团队已将其标记为“不推荐使用”(obsoleted in .NET 5+ 的某些分析规则中),现代代码更倾向用专用方法如
CloneDeep()或构造函数传参
示例(显式声明为深拷贝):
class Person : ICloneable {public string Name; public Address Addr;
public object Clone() => new Person {
Name = this.Name,
Addr = this.Addr == null ? null : new Address { City = this.Addr.City }
};
}
实用建议:按场景选方案
- 只要复制一层字段,且不含复杂引用 → 用
MemberwiseClone - 数据简单、可序列化、不追求极致性能 → 用
JsonSerializer深拷贝 - 需要精确控制每一步(比如跳过某些字段、处理循环引用、调用自定义初始化)→ 手写克隆逻辑
- 团队协作或公共库中 → 避免仅靠
ICloneable,改用命名清晰的方法如With(...)、DeepCopy()或记录类型(record)的with表达式
基本上就这些。深浅拷贝本质是对象图遍历策略的选择,关键是理解你的数据结构和共享意图,而不是迷信某个接口或方法名。









