【转】C#浅度克隆和深度克隆

原文链接:https://blog.youkuaiyun.com/ni_zhi/article/details/5764694

C#复制有深度复制和浅度复制,与赋值运算(=)进行复制的比较。

首先,定义一个类Content作为后面要用的字段类型,Content包含一个int型字段Val

public class Content  
{  
    public int Val;  
}  

然后,定义值类型MyStructMyClass,各包含一个值类型字段和一个引用类型字段。并且它们都支持ICloneable接口,实现了深度复制和浅度复制。

// MyStruct  
public struct MyStruct : ICloneable  
{  
    public int Val;  
    public Content MyContent;  
  
    public MyStruct(int val, int contentVal)  
    {  
        Val = val;  
        MyContent = new Content();  
        MyContent.Val = contentVal;  
    }   
  
    public object GetCopy()  
    {  
        return MemberwiseClone();  
    }  
  
    public object Clone()  
    {  
        MyStruct clonedStruct = new MyStruct(Val, MyContent.Val);  
        return clonedStruct;  
    }  
}  
  
// MyClass  
public class MyClass : ICloneable  
{  
    public int Val;  
    public Content MyContent = new Content();  
  
    public MyClass(int newVal, int newContentVal)  
    {  
        Val = newVal;  
        MyContent.Val = newContentVal;  
    }  
  
    public object GetCopy()  
    {  
        return MemberwiseClone();  
    }    
  
    public object Clone()  
    {  
        MyClass clonedClass = new MyClass(Val, MyContent.Val);  
        return clonedClass;  
    }  
}  

接着,Main函数,对MyClassMyStruct都分别用了三种复制方法,输出它们的值,然后改变源对象的值,再输出。

class Program  
{  
    static void Main(string[] args)  
    {  
        // 引用类型复制测试  
         Console.WriteLine("Reference Type");  
        MyClass c1 = new MyClass(1, 1);  
        MyClass c2 = c1;                       // 赋值复制  
         MyClass c3 = (MyClass)c1.GetCopy();     // 浅度复制  
         MyClass c4 = (MyClass)c1.Clone();       // 深度复制  
   
         Console.WriteLine("c1, {0}, {1}", c1.Val, c1.MyContent.Val);  
        Console.WriteLine("c2, {0}, {1}", c2.Val, c2.MyContent.Val);  
        Console.WriteLine("c3, {0}, {1}", c3.Val, c3.MyContent.Val);  
        Console.WriteLine("c4, {0}, {1}", c4.Val, c4.MyContent.Val);  
  
        c1.Val = 2;  
        c1.MyContent.Val = 2;  
        Console.WriteLine("Source   c1, {0}, {1}", c1.Val, c1.MyContent.Val);  
        Console.WriteLine("Assign   c2, {0}, {1}", c2.Val, c2.MyContent.Val);  
        Console.WriteLine("Shallow  c3, {0}, {1}", c3.Val, c3.MyContent.Val);  
        Console.WriteLine("Deep     c4, {0}, {1}", c4.Val, c4.MyContent.Val);  
        Console.WriteLine();  
  
        // 值类型复制测试  
         Console.WriteLine("Value Type");  
        MyStruct s1 = new MyStruct(1, 1);  
        MyStruct s2 = s1;                       // 赋值赋值  
         MyStruct s3 = (MyStruct)s1.GetCopy();   // 浅度复制  
         MyStruct s4 = (MyStruct)s1.Clone();     // 深度复制  
         Console.WriteLine("s1, {0}, {1}", s1.Val, s1.MyContent.Val);  
        Console.WriteLine("s2, {0}, {1}", s2.Val, s2.MyContent.Val);  
        Console.WriteLine("s3, {0}, {1}", s3.Val, s3.MyContent.Val);  
        Console.WriteLine("s4, {0}, {1}", s4.Val, s4.MyContent.Val);  
  
        s1.Val = 2;  
        s1.MyContent.Val = 2;  
        Console.WriteLine("Source   s1, {0}, {1}", s1.Val, s1.MyContent.Val);  
        Console.WriteLine("Assign   s2, {0}, {1}", s2.Val, s2.MyContent.Val);  
        Console.WriteLine("Shallow  s3, {0}, {1}", s3.Val, s3.MyContent.Val);  
        Console.WriteLine("Deep     s4, {0}, {1}", s4.Val, s4.MyContent.Val);  
  
        Console.ReadKey();  
    }  
}   

最后,结果如图,重要的是红色矩形框中的内容

 

结论:

对于引用类型的变量,赋值复制后 对源对象值类型字段和引用类型字段的改变 都会反应在目标对象中;对于值类型的变量,赋值复制后 对源对象值类型字段的改变不会反应在目标对象,而对源对象引用类型字段的改变则会反应在目标对象中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值