C# 值拷贝、引用拷贝、浅拷贝、深拷贝

值拷贝

定义:直接复制变量的值,适用于基本数据类型(如int, float, char等)。在 C# 中,值类型(基本数据类型和结构体)默认使用值拷贝。

特点:创建原始值的完全独立副本,修改副本不会影响原始值

示例

cs 复制代码
int a = 10;
int b = a; // 值拷贝
b = 20;    // 修改b不会影响a

打印:

引用拷贝

定义:复制对象的引用(内存地址),不创建新对象。对于引用类型(类、接口、委托、数组等),赋值操作默认是引用拷贝。

特点:新变量和原变量指向同一个对象,修改其中任一对象都会影响另一个

示例

cs 复制代码
class Person { public string Name; }
var person1 = new Person() { Name = "小明" };
var person2 = person1;

person2.Name = "小红";

打印:

浅拷贝

定义:创建一个新的对象。如果数据是基本类型,拷贝的就是基本类型的值;如果数据是引用类型,则拷贝的就是内存地址即引用。

特点

1、修改克隆对象中的基本类型数据不会影响原对象的基本类型数据。

2、修改克隆对象中的引用类型数据会影响原对象的值类型数据,本质上,两者的引用类型数据是同一个。

示例

cs 复制代码
class Person : ICloneable
{
    public string Name;
    public int Id;
    public Address Address; // 引用类型字段

    public object Clone()
    {
        return this.MemberwiseClone(); // 浅拷贝
    }
}

class Address { public string Street; }

//--------------------------------------------------------

Person person1 = new Person { 
    Name = "Alice", 
    Id = 666,
    Address = new Address { Street = "北京" }
};

Person person2 = (Person)person1.Clone();//浅拷贝

person2.Name = "Bob"; 
person2.Id = 123;
person2.Address.Street = "上海"; // 会影响p1的Address

打印:

深拷贝

定义:完全复制原始对象及其所有嵌套对象,创建一个独立的,全新的对象,在深拷贝中,原始对象与新对象之间没有任何共享的引用

特点:修改克隆对象中的基本类型数据或者引用类型数据都不会影响原对象的数据,它们是完全独立的。

示例

cs 复制代码
class Person : ICloneable
{
    public string Name;
    public int Id;
    public Address Address; // 引用类型字段

    public object Clone()
    {
        Person cloned = (Person)this.MemberwiseClone();
        cloned.Address = new Address { Street = this.Address.Street }; // 深拷贝引用类型字段
        return cloned;
    }
}

class Address { public string Street; }

//--------------------------------------------------------

Person person1 = new Person { 
    Name = "Alice", 
    Id = 666,
    Address = new Address { Street = "北京" }
};

Person person2 = (Person)person1.Clone();//深拷贝

person2.Name = "Bob"; 
person2.Id = 123;
person2.Address.Street = "上海"; 

打印:

总结

拷贝类型 实现方法 特点 适用场景 性能
值拷贝 直接赋值 创建完全独立副本 值类型(int, float, struct等)
引用拷贝 直接赋值 共享同一对象引用 引用类型(class)的简单传递
浅拷贝 MemberwiseClone 复制值类型字段,共享引用类型字段 对象结构简单或引用字段无需独立 中等
深拷贝 手动实现/序列化 完全独立的对象图 复杂对象需要完全独立副本 较低

知识补充

对复杂对象使用序列化实现深拷贝

本示例使用Newtonsoft实现,也可以使用其他的序列化方法实现

cs 复制代码
using Newtonsoft.Json;
class Person : ICloneable
{
    public string Name;
    public int Id;
    public Address Address; // 引用类型字段

    public object Clone()
    {
        string json = JsonConvert.SerializeObject(this);
        return JsonConvert.DeserializeObject<Person>(json);
    }
}

class Address { public string Street; }
特性 序列化方法 普通手动方法
实现复杂度 简单,一行代码处理整个对象图 复杂,需要为每个引用类型字段手动实现
维护成本 低,对象结构变化不影响拷贝逻辑 高,对象结构变化需同步修改拷贝方法
性能 较低(涉及序列化/反序列化开销) 较高(直接内存操作)
循环引用处理 自动处理 需手动处理,否则会栈溢出
私有字段拷贝 可以拷贝私有字段 只能拷贝可访问字段

处理集合类对象的拷贝

浅拷贝

1. 使用构造函数浅拷贝
cs 复制代码
class Person
{
    public string Name;
    public int Id;
}

List<Person> originalList = new List<Person> { new Person
{
    Name = "Alice" ,Id = 111
    } };

List<Person> shallowCopy = new List<Person>(originalList); // 浅拷贝

// 修改新集合中的元素会影响原集合
shallowCopy[0].Name = "Bob";
2. 使用 LINQ 的 ToList()/ToArray()实现浅拷贝
cs 复制代码
class Person
{
    public string Name;
    public int Id;
}

List<Person> originalList = new List<Person> { new Person
{
    Name = "Alice" ,Id = 111
    } };

List<Person> shallowCopy = originalList.ToList();// 浅拷贝

// 修改新集合中的元素会影响原集合
shallowCopy[0].Name = "Bob";

深拷贝

手动实现

先在Person类中实现深拷贝方法

cs 复制代码
class Person : ICloneable
{
    public string Name;
    public int Id;
    public Address Address; // 引用类型字段

    public object Clone()
    {
        string json = JsonConvert.SerializeObject(this);
        return JsonConvert.DeserializeObject<Person>(json);
    }
}

 List<Person> originalList = new List<Person> { new Person
 {
     Name = "Alice" ,Id = 111
     } };

List<Person> deepCopy = new List<Person>();
foreach (var data in originalList)
{
    deepCopy.Add((Person)data.Clone());
}

deepCopy[0].Name = "Bob";
使用 LINQ + 元素拷贝
cs 复制代码
 List<Person> deepCopy = originalList.Select(p => (Person)p.Clone()).ToList();
相关推荐
csdn_aspnet4 小时前
C# 求n边凸多边形的对角线数量(Find number of diagonals in n sided convex polygon)
开发语言·算法·c#
武藤一雄9 小时前
C# 设计模式大全(第一弹|7种)
microsoft·设计模式·微软·c#·.net·.netcore
格林威10 小时前
Baumer相机锂电池极片裁切毛刺检测:防止内部短路的 5 个核心方法,附 OpenCV+Halcon 实战代码!
开发语言·人工智能·数码相机·opencv·计算机视觉·c#·视觉检测
向上的车轮11 小时前
熟悉C#如何转TypeScript——SDK与包引用
开发语言·typescript·c#
CSharp精选营12 小时前
Dispose 不释放?C# 资源泄漏的 3 种隐蔽场景排查
c#·资源泄漏
unicrom_深圳市由你创科技13 小时前
LabVIEW和C#在工业控制中的应用差异是什么?
fpga开发·c#·labview
唐青枫14 小时前
C#.NET Consul + Steeltoe 深入解析:服务注册发现、健康检查与微服务接入
c#·.net
DowneyJoy15 小时前
【Unity3D补充知识点】常用数据结构分析-集合(List<T>)
数据结构·unity·c#·list
格林威15 小时前
Baumer相机铝型材表面划伤长度测量:实现损伤量化评估的 5 个关键技术,附 OpenCV+Halcon 实战代码!
开发语言·人工智能·数码相机·opencv·计算机视觉·c#·工业相机
DowneyJoy16 小时前
【Unity3D补充知识点】常用数据结构分析-数组(Array)
数据结构·unity·c#