栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > .Net

.Net 对象的浅拷贝与深拷贝

.Net 更新时间:发布时间: 百科书网 趣学号
浅拷贝

浅拷贝拷贝的是对象的引用,实际上还是指向同一个对象,改变其中任意对象的值,另一个对象的值也会跟着改变。

public class Animal
{
    public string Name { get; set; }
}

Animal a1 = new Animal() { Name = "小狗" };
Animal a2 = a1;                 // 这里就是浅拷贝
a2.Name = "小狗钱钱";           // 改变 a2.Name 的值
Console.WriteLine(a1.Name);     // 小狗钱钱,a1 跟着改变了,因为它们都指向同一个对象
Console.WriteLine(a2.Name);     // 小狗钱钱
深拷贝 简单的深拷贝

深拷贝就是连被引用的对象也拷贝一份出来,改变新拷贝对象的值不会影响原来对象的值。.Net中所有类型的根类定义了一个 protected 方法MemberwiseClone() ,使用这个方法可以实现简单的深拷贝

public class Employee
{
    public string Name { get; set; }

    public Employee Copy() => this.MemberwiseClone() as Employee;
}

Employee e1 = new Employee() { Name = "张三" };
Employee e2 = e1.Copy();

e2.Name = "李四";
Console.WriteLine(e1.Name);                     // 张三
Console.WriteLine(e2.Name);                     // 李四
Console.WriteLine(ReferenceEquals(e1, e2));     // False

由上面可以看出,改变拷贝对象(e2所指向的对象)的值不会影响 e1 所指向对象的值,再通过ReferenceEquals方法比较两个对象的引用,同样不相同,所以确实实现了“深拷贝”。

完全深拷贝

上面的深拷贝对象只有简单数据类型,如果引用了复杂的对象,那么MemberwiseClone方法还能完成“深拷贝”吗?

public class Employee
{
    public string Name { get; set; }

    public Dog Dog { get; set; }  // 新增复杂对象

    public Employee Copy() => this.MemberwiseClone() as Employee;
}

public class Dog
{
    public string Name { get; set; }
}

Dog dog = new Dog() { Name = "小狗钱钱" };
Employee e1 = new Employee() { Name = "张三", Dog = dog };
Employee e2 = e1.Copy();

e2.Name = "李四";
Console.WriteLine(e1.Name);                             // 张三
Console.WriteLine(e2.Name);                             // 李四
Console.WriteLine(ReferenceEquals(e1, e2));             // False

// 新增比较
e1.Dog.Name = "小狗";
Console.WriteLine(e1.Dog.Name);                         // 小狗
Console.WriteLine(e2.Dog.Name);                         // 小狗
Console.WriteLine(ReferenceEquals(e1.Dog, e2.Dog));     // True

由上面新增比较可以看出,引用了复杂对象类型的属性,使用MemberwiseClone方法进行拷贝时,并不能实现“完全的深拷贝”。实现“完全深拷贝”可以通过二进制格式序列化和反序列化的方式:

public static object Clone(object obj)
{
    using (MemoryStream ms = new MemoryStream())    // 创建内存流
    {
        BinaryFormatter bf = new BinaryFormatter(); // 以二进制格式进行序列化
        bf.Serialize(ms, obj);

        ms.Seek(0, 0);
        object res = bf.Deserialize(ms);            // 反序列化当前实例到一个object
        return res;
    }
}

Employee e3 = Clone(e1) as Employee;                    // 把 e1 拷贝到 e3
e1.Dog.Name = "小狗2";
Console.WriteLine(e1.Dog.Name);                         // 小狗2
Console.WriteLine(e3.Dog.Name);                         // 小狗1
Console.WriteLine(ReferenceEquals(e1, e3));             // False
Console.WriteLine(ReferenceEquals(e1.Dog, e3.Dog));     // False

好了,到这里可以看到,我们已经实现了“完全深拷贝”。

值类型的复制都可以看做是深拷贝。

References

MemberwiseClone创建一个浅表副本。过程是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型,则对该字段执行逐位复制;如果字段是引用类型,则复制引用但不复制引用对象。

转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/1065982.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号