C#中的深拷貝與淺拷貝

淺拷貝和深拷貝之間的區別:

    淺拷貝是指將對象中的數值類型的字段拷貝到新的對象中,而對象中的引用型字段則指複製它的一個引用到目標對象。如果改變目標對象中引用型字段的值他將反映在原始對象中,也就是說原始對象中對應的字段也會發生變化。

   深拷貝與淺拷貝不同的是對於引用的處理,深拷貝將會在新對象中創建一個新的和原始對象中對應字段相同(內容相同)的字段,也就是說這個引用和原始對象的引用是不同的,我們在改變新對象中的這個字段的時候是不會影響到原始對象中對應字段的內容。

所以對於原型模式(prototype pattern)也有不同的兩種處理方法:對象的淺拷貝和深拷貝

MemberwiseClone 方法創建一個淺表副本,方法是創建一個新對象,然後將當前對象的非靜態字段複製到該新對象。如果字段是值類型的,則對該字段執行逐位複製。如果字段是引用類型,則複製引用但不復制引用的對象;因此,原始對象及其複本引用同一對象。深拷貝,即實現ICloneable接口.ICloneable可用於深拷貝和淺拷貝。

.net提供了一個ICloneable接口,該接口下有一個Clone()方法,你可以實現它用來實現你自己的克隆方式,比如深克隆或是淺克隆,MemberwiseClone()是object類中的一個方法,用來實現類的淺克隆

下面是一個深拷貝與淺拷貝的Model,僅供參考

[Serializable]
    public class InvoiceDetailResponse : IDeepCopy, IShallowCopy
    {
         
        public Guid merchant_id { get; set; }
        /// <summary>
        /// 名稱
        /// </summary>
        public string uname { get; set; }
       
        /// <summary>
        /// 淺拷貝
        /// </summary>
        /// <returns></returns>
        public object ShallowCopy()
        {
            return this.MemberwiseClone();
        }
       /// <summary>
        /// 深拷貝 【不建議使用二進制流方法,此方法即使在類前面加了可序列化標誌,調用該方法時也會報未序列化錯誤】,推薦使用反射方式
        /// </summary>
        /// <returns></returns>
        public object DeepCopy()
        {
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryFormatter bFormatter = new BinaryFormatter();
                bFormatter.Serialize(stream, this);
                stream.Seek(0, SeekOrigin.Begin);
                return (InvoiceDetailResponse)bFormatter.Deserialize(stream);
            }
        }
 


    }
    /// <summary>
    /// 深拷貝接口
    /// </summary>
    interface IDeepCopy
    {
        object DeepCopy();
    }

    /// <summary>
    /// 淺拷貝接口
    /// </summary>
    interface IShallowCopy
    {
        object ShallowCopy();
    }
利用反射實現

public static T DeepCopyByReflection<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.Static|BindingFlags.Instance);
  foreach(var field in fields)
  {
    try
    {
      field.SetValue(retval, DeepCopyByReflection(field.GetValue(obj)));
    }
    catch { }
  }

  return (T)retval;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章