c# 深克隆与浅克隆

首先了解一下什么是深克隆与浅克隆

#中有两种类型变量,一种是值类型变量,一种是引用类型变量。

对于前者,copy是属于全盘复制;而对于后者,一般的copy只是浅copy,只copy引用地址,相当于只传递一个引用指针一样。因此对于后者进行真正copy的时候,也是最费事的,具体的说,必须为其实现 ICloneable接口中提供的Clone方法,从而产生一个全新的对象。

浅拷贝(影子克隆):只复制对象的基本类型,对象类型,仍属于原来的引用. 
深拷贝(深度克隆):不紧复制对象的基本类,同时也复制原对象中的对象.就是说完全是新对象产生的.

 

浅拷贝和深拷贝之间的区别:

    浅拷贝是指将对象中的数值类型的字段拷贝到新的对象中,而对象中的引用型字段则指复制它的一个引用到目标对象。如果改变目标对象中引用型字段的值他将反映在原始对象中,也就是说原始对象中对应的字段也会发生变化。

   深拷贝与浅拷贝不同的是对于引用的处理,深拷贝将会在新对象中创建一个新的和原始对象中对应字段相同(内容相同)的字段,也就是说这个引用和原始对象的引用是不同的,我们在改变新对象中的这个字段的时候是不会影响到原始对象中对应字段的内容。

所以对于原型模式(prototype pattern)也有不同的两种处理方法:对象的浅拷贝和深拷贝

MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。深拷贝,即实现ICloneable接口.ICloneable可用于深拷贝和浅拷贝。

.net提供了一个ICloneable接口,该接口下有一个Clone()方法,你可以实现它用来实现你自己的克隆方式,比如深克隆或是浅克隆,MemberwiseClone()是object类中的一个方法,用来实现类的浅克隆

 以上摘自  https://www.cnblogs.com/tinya/p/4511120.html

在这里讲解2中深克隆方式

1.序列化的方式

[Serializable]
class MyClass//: ICloneable
{
    public int id;
    public List str;

    public MyClass DeepClone()
    {
        BinaryFormatter bFormatter = new BinaryFormatter();
        MemoryStream stream = new MemoryStream();
        bFormatter.Serialize(stream, this);
        stream.Seek(0, SeekOrigin.Begin);
        return (MyClass)bFormatter.Deserialize(stream);
    }
}
 MyClass myClass1 = new MyClass();
        myClass1.id = 1;
        myClass1.str = new List() ;
        myClass1.str.Add( "sadsa");
        myClass1.str.Add("45454");

        MyClass myClass2 = new MyClass();
        myClass2 =myClass1.DeepClone();
        myClass2.id = 3;
        myClass2.str.Add("22");

这样myclass2就是一个全新的对象了

2.反射的方式

 public static object CopyObject(object obj)
    {
        object targetDeepCopyObj;

        if (obj == null)
        {
            Debug.Log("copy obj is null");
        }
        var targetType = obj.GetType();
        //值类型  
        if (targetType.IsValueType == true)
        {
            targetDeepCopyObj = obj;
        }
        //引用类型   
        else
        {
            targetDeepCopyObj = Activator.CreateInstance(targetType);   //创建引用对象   
            MemberInfo[] memberCollection = obj.GetType().GetMembers();

            foreach (MemberInfo member in memberCollection)
            {
                if (member.MemberType == MemberTypes.Field)
                {
                    FieldInfo field = (FieldInfo)member;
                    object fieldValue = field.GetValue(obj);
                    if (fieldValue is ICloneable)
                    {
                        field.SetValue(targetDeepCopyObj, (fieldValue as ICloneable).Clone());
                    }
                    else
                    {
                        field.SetValue(targetDeepCopyObj, CopyObject(fieldValue));
                    }

                }
                else if (member.MemberType == MemberTypes.Property)
                {
                    PropertyInfo myProperty = (PropertyInfo)member;
                    MethodInfo info = myProperty.GetSetMethod(false);
                    if (info != null)
                    {
                        object propertyValue = myProperty.GetValue(obj, null);
                        if (propertyValue is ICloneable)
                        {
                            myProperty.SetValue(targetDeepCopyObj, (propertyValue as ICloneable).Clone(), null);
                        }
                        else
                        {
                            myProperty.SetValue(targetDeepCopyObj, CopyObject(propertyValue), null);
                        }
                    }
                }
            }
        }
        return targetDeepCopyObj;
    }

这种方式测试时如果一个类中有List时会出现报错 类型不匹配的情况  具体原因 我也不知

   以上就是一个对象赋值时直接引用地址 花了时间网上搜索总结的  希望对你有用...........  

你可能感兴趣的:(c# 深克隆与浅克隆)