在C#编程中,对象复制是日常开发里经常遇到的需求,根据复制的层级不同,分为浅拷贝和深拷贝两种类型,不同的实现方式对应不同的使用场景,开发者需要根据实际业务需求选择合适的方案。

浅拷贝与深拷贝的核心区别
浅拷贝指的是在复制对象时,对于值类型的字段会直接复制其数值,对于引用类型的字段,只会复制该引用本身,而不会复制引用指向的实际对象。也就是说,拷贝后的对象和原对象的引用类型字段会指向同一个内存地址,修改其中一个对象的引用类型字段内容,另一个对象也会受到影响。
深拷贝则是完全复制整个对象的所有层级,包括所有引用类型字段指向的对象,拷贝后的对象和原对象完全独立,修改任意一个对象的内容都不会影响另一个对象。
通过ICloneable接口实现拷贝
ICloneable是C#提供的用于支持对象克隆的接口,内部仅定义了一个Clone方法,开发者可以在自定义类中实现该接口,自定义拷贝的逻辑。
实现浅拷贝
Object类本身提供了MemberwiseClone方法,该方法可以创建当前对象的浅拷贝,因此实现浅拷贝时直接调用该方法即可。
using System;
namespace CloneDemo
{
public class Person : ICloneable
{
public string Name { get; set; }
public int Age { get; set; }
// 引用类型字段
public Address AddressInfo { get; set; }
// 实现浅拷贝,直接调用MemberwiseClone
public object Clone()
{
return this.MemberwiseClone();
}
}
public class Address
{
public string City { get; set; }
public string Street { get; set; }
}
class Program
{
static void Main(string[] args)
{
Person original = new Person
{
Name = "张三",
Age = 25,
AddressInfo = new Address { City = "北京", Street = "朝阳路" }
};
// 执行浅拷贝
Person shallowCopy = (Person)original.Clone();
// 修改拷贝对象的引用类型字段内容
shallowCopy.AddressInfo.City = "上海";
Console.WriteLine($"原对象城市:{original.AddressInfo.City}");
Console.WriteLine($"拷贝对象城市:{shallowCopy.AddressInfo.City}");
}
}
}
上述代码中,修改拷贝对象的AddressInfo.City后,原对象的对应字段也被修改,说明浅拷贝下引用类型字段共享同一个实例。
实现深拷贝
要实现深拷贝,需要在Clone方法中手动对所有的引用类型字段进行复制,确保所有层级的引用对象都被重新创建。
using System;
namespace CloneDemo
{
public class Person : ICloneable
{
public string Name { get; set; }
public int Age { get; set; }
public Address AddressInfo { get; set; }
public object Clone()
{
// 创建新的Person对象
Person newPerson = new Person
{
Name = this.Name,
Age = this.Age
};
// 如果AddressInfo不为空,创建新的Address实例
if (this.AddressInfo != null)
{
newPerson.AddressInfo = new Address
{
City = this.AddressInfo.City,
Street = this.AddressInfo.Street
};
}
return newPerson;
}
}
public class Address
{
public string City { get; set; }
public string Street { get; set; }
}
class Program
{
static void Main(string[] args)
{
Person original = new Person
{
Name = "李四",
Age = 30,
AddressInfo = new Address { City = "广州", Street = "天河路" }
};
Person deepCopy = (Person)original.Clone();
deepCopy.AddressInfo.City = "深圳";
Console.WriteLine($"原对象城市:{original.AddressInfo.City}");
Console.WriteLine($"拷贝对象城市:{deepCopy.AddressInfo.City}");
}
}
}
此时修改拷贝对象的AddressInfo.City,原对象的对应字段不会变化,说明深拷贝成功,两个对象完全独立。
通过序列化实现深拷贝
如果对象的层级结构比较复杂,手动实现深拷贝会非常繁琐,此时可以通过序列化的方式实现通用的深拷贝。思路是将对象序列化为字节流或者字符串,再反序列化为新的对象,这样得到的就是完全独立的深拷贝对象。
二进制序列化实现深拷贝
使用二进制序列化需要给类标记[Serializable]特性,否则会抛出异常。
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace CloneDemo
{
[Serializable]
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Address AddressInfo { get; set; }
}
[Serializable]
public class Address
{
public string City { get; set; }
public string Street { get; set; }
}
public static class DeepCopyHelper
{
// 二进制序列化实现深拷贝
public static T DeepCopyByBinary<T>(T obj)
{
if (obj == null)
{
return default(T);
}
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
// 序列化对象到内存流
formatter.Serialize(ms, obj);
// 将流位置重置到开头
ms.Seek(0, SeekOrigin.Begin);
// 反序列化为新对象
return (T)formatter.Deserialize(ms);
}
}
}
class Program
{
static void Main(string[] args)
{
Person original = new Person
{
Name = "王五",
Age = 28,
AddressInfo = new Address { City = "杭州", Street = "西湖路" }
};
Person deepCopy = DeepCopyHelper.DeepCopyByBinary(original);
deepCopy.AddressInfo.City = "成都";
Console.WriteLine($"原对象城市:{original.AddressInfo.City}");
Console.WriteLine($"拷贝对象城市:{deepCopy.AddressInfo.City}");
}
}
}
需要注意的是,BinaryFormatter在.NET 5及更高版本中已被标记为过时,不过在.NET Framework环境下仍然可以正常使用。
JSON序列化实现深拷贝
使用JSON序列化是更通用的方案,不需要标记[Serializable]特性,这里以Newtonsoft.Json为例演示实现方式。
using System;
using Newtonsoft.Json;
namespace CloneDemo
{
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Address AddressInfo { get; set; }
}
public class Address
{
public string City { get; set; }
public string Street { get; set; }
}
public static class DeepCopyHelper
{
// JSON序列化实现深拷贝
public static T DeepCopyByJson<T>(T obj)
{
if (obj == null)
{
return default(T);
}
string json = JsonConvert.SerializeObject(obj);
return JsonConvert.DeserializeObject<T>(json);
}
}
class Program
{
static void Main(string[] args)
{
Person original = new Person
{
Name = "赵六",
Age = 32,
AddressInfo = new Address { City = "武汉", Street = "光谷路" }
};
Person deepCopy = DeepCopyHelper.DeepCopyByJson(original);
deepCopy.AddressInfo.City = "长沙";
Console.WriteLine($"原对象城市:{original.AddressInfo.City}");
Console.WriteLine($"拷贝对象城市:{deepCopy.AddressInfo.City}");
}
}
}
JSON序列化的方式兼容性更好,只要对象可以被正常序列化和反序列化,就能实现深拷贝,适合大多数场景使用。
不同实现方式的适用场景
- 如果对象结构简单,引用类型字段少,且只需要浅拷贝,直接使用ICloneable结合MemberwiseClone是最便捷的方式。
- 如果需要深拷贝且对象层级不复杂,手动实现ICloneable的深拷贝逻辑可以保证性能,避免序列化的开销。
- 如果对象层级复杂,或者需要通用的深拷贝能力,使用序列化(尤其是JSON序列化)的方式可以减少重复代码,提高开发效率。
在实际开发中,需要根据对象的复杂度、性能要求以及项目的依赖情况,选择最合适的对象复制实现方案。
C#ICloneable深拷贝浅拷贝序列化修改时间:2026-06-08 20:51:39