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();
相关推荐
每日出拳老爷子2 小时前
[C#] 使用TextBox换行失败的原因与解决方案:换用RichTextBox的实战经验
开发语言·c#
阿蒙Amon11 小时前
C#随机数生成全面详解:从基础到高级应用
服务器·网络·c#
开开心心_Every11 小时前
便捷的电脑自动关机辅助工具
开发语言·人工智能·pdf·c#·电脑·音视频·sublime text
我要打打代码14 小时前
C#Winform窗体显示模糊的问题
c#
阿蒙Amon14 小时前
C#正则表达式全面详解:从基础到高级应用
开发语言·正则表达式·c#
水果里面有苹果16 小时前
19-C#静态方法与静态类
java·开发语言·c#
吃着火锅x唱着歌16 小时前
LeetCode 3306.元音辅音字符串计数2
算法·leetcode·c#
格林威21 小时前
Baumer工业相机堡盟工业相机如何通过DeepOCR模型识别判断数值和字符串的范围和相似度(C#)
开发语言·人工智能·python·数码相机·计算机视觉·c#·视觉检测
向宇it1 天前
Unity Universal Render Pipeline/Lit光照材质介绍
游戏·unity·c#·游戏引擎·材质