zoukankan      html  css  js  c++  java
  • 浅复制

    Shallow Copy

    System.Object.MemberwiseClone();受保护的方法。

    Deep Copy

    实现 ICloneable 接口并重写 Clone() 方法:

    public class A : ICloneable{
        public A() {}
        public object Clone() {
            A objA = new A();
            return objA;
       }
    }
    

    下面总结了 深拷贝 的几种常用方法

    /// BY IFormatter
    public T DeepCloneObj<T>(T obj)
    {
    	using (Stream objectStream = new MemoryStream())
    	{
    		IFormatter formatter = new BinaryFormatter();
    		formatter.Serialize(objectStream, obj);
    		objectStream.Seek(0, SeekOrigin.Begin);
    		object objDeep = formatter.Deserialize(objectStream);
    		return (T)objDeep;
    	}
    } 
    
    /// BY BinaryFormatter
    private static T DeepCopyObj<T>(T obj)
    {
    	object retObj = null;
    	using (MemoryStream ms = new MemoryStream())
    	{
    		BinaryFormatter bf = new BinaryFormatter();
    
    		//序列化成流
    		bf.Serialize(ms, obj);
    		ms.Seek(0, SeekOrigin.Begin);
    
    		//反序列化成对象
    		retObj = bf.Deserialize(ms);
    
    		ms.Close();
    	}
    	return (T)retObj;
    }
    
    /// BY XmlSerializer
    public static T DeepCopyByXml<T>(T obj)
    {
    	object retVal;
    	using (MemoryStream ms = new MemoryStream())
    	{
    		XmlSerializer xml = new XmlSerializer(typeof(T));
    		xml.Serialize(ms, obj);
    		ms.Seek(0, SeekOrigin.Begin);
    		retVal = xml.Deserialize(ms);
    		ms.Close();
    	}
    	return (T)retVal;
    }
    
    /// BY DataContractSerializer,需要Silverlight支持
    public static T DeepCopy<T>(T obj)
    {
    	object retval;
    	using (MemoryStream ms = new MemoryStream())
    	{
    		DataContractSerializer ser = new DataContractSerializer(typeof(T));
    		ser.WriteObject(ms, obj);
    		ms.Seek(0, SeekOrigin.Begin);
    		retval = ser.ReadObject(ms);
    		ms.Close();
    	}
    	return (T)retval;
    }
    
    /// BY 反射
    public static T DeepCopyByReflect<T>(T obj)
    {
    	//如果是字符串或值类型则直接返回
    	if (obj is string || obj.GetType().IsValueType)
    		return obj;
    
    	object retval = Activator.CreateInstance(obj.GetType());
    	FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public
    		| BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
    	
    	foreach (FieldInfo field in fields)
    	{
    		try { 
    			field.SetValue(retval, DeepCopyByReflect(field.GetValue(obj))); 
    		}
    		catch { }
    	}
    	return (T)retval;
    }
    

    其中,前4种方法类似,最后一种方法是通过反射实现深拷贝。 注意,类对象应该 [Serializable] 标识。

    此外,可以通过如下方法,判断前后2个对象地址是否不同

    object.ReferenceEquals(per1., per2).ToString()  // True or False
    

    也可以分别获取2个对象的地址比较,亦可

    /// <summary>
    /// 获取引用类型的内存地址
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static string getMemAddr(object obj)     
    {
    	GCHandle h = GCHandle.Alloc(obj, GCHandleType.WeakTrackResurrection);
    	IntPtr addr = GCHandle.ToIntPtr(h);
    	return "0x" + addr.ToString("X");
    }
    

    除单独的深拷贝方法,也可以直接类对象内部实现

    [Serializable]  
    public class D : ICloneable 
    {	
    	public object Clone()  
        {  
            return this.MemberwiseClone();  //浅拷贝
        }  
    
        //浅拷贝  
        public D ShallowClone()  
        {  
            return this.Clone() as D;  
        }  
    	
    	//深拷贝  
        public D DeepClone()
    	{
    		DeepCopyByXXX();
    	}
    }
    

    具体参见:C#对象复制 - ICloneable

      

  • 相关阅读:
    Quarts 执行定时任务失败(.job.entity.ScheduleJobEntity cannot be cast to com.)
    Map与String互相转化
    weui中的picker滑动报错
    weui中的picker使用js进行动态绑定数据
    ajax跨域问题解决方案(jsonp的使用)
    pdm文件打开方式
    删除静态页面的html
    js同时获取多个共同class内容标签内容集合
    内外网同时使用
    win10重装系统修改信息
  • 原文地址:https://www.cnblogs.com/wjcx-sqh/p/5975408.html
Copyright © 2011-2022 走看看