c#深拷贝与浅拷贝

一、浅拷贝

1、通俗来说,浅拷贝就是单纯的把一个对象指向的地址给另外一个对象,例如:

Person p1= new Person();
Person p2 =p1;
//这就是我们常用的——浅拷贝,现在p1,p2指向的是同一个地址
//假如Perso类中有一个字段name
p1.name = "李四";
p2.name ="张三"//现在p1.name 变成了张三,可以理解为实际上p2并没有开辟新的空间

2、如果我们想复制p1的属性值,但是又想做一些改动且不影响p1,就会用到深拷贝。

二、深拷贝

1、个人认为,深拷贝实际上是利用反射机制中的Activator.CreateInstance方法开辟了新的空间,下面是用反射实现的深拷贝

public static T DeepCopyByReflection<T>(T obj)
        {
        //筛选出除了string之外的引用类型,若obj为引用类型则继续往下
if (obj is string || obj.GetType().IsValueType) return obj;         //声明一个object对象来接收该方法创建的实例,新创建的实例类型跟obj一样 object retval = Activator.CreateInstance(obj.GetType());
        //获取obj所在类中的所有字段 FieldInfo[] fields
= obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); foreach (var field in fields) { try {
            //这是最关键的一步,相当于开始拷贝obj实例的值,retval=obj,但是现在两者不是指向一个地址 field.SetValue(retval, DeepCopyByReflection(field.GetValue(obj))); }
catch { } }         //返回实例 return (T)retval; }



//在主函数中调用
Person p3=
DeepCopyByReflection(p1)
//这个时候在主函数中调用这个方法之后,就相当于新建了一个实例,且该实例拥有跟p1一模一样的值,但是改动p3不会影响p1.

 

2、二进制实现深拷贝,这里不做过多解释,有兴趣的可以深入了解。注意:用这个方法必须在实例类的前面加上[Serialize]特性。

public static T DeepCopyByBinary<T>(T obj)
        {
            object retval;
            using(MemoryStream ms= new MemoryStream())
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(ms, obj);
                ms.Seek(0, SeekOrigin.Begin);
                retval = bf.Deserialize(ms);
                
            };

            return (T)retval;
        }

 

posted @ 2022-07-29 20:48  Darius丶段  阅读(719)  评论(0编辑  收藏  举报