记录一下C#深拷贝的几种方式

一、C#中预定义数据类型

        1》值类型

         2》引用类型

两种类型的不同点:

       概念:值类型直接存储其值,而引用类型存储对值的引用

       存储:值类型存储在堆栈(stack)上,而引用类型存储在托管堆上(managed heap)。

当使用值类型,进行赋值的操作时,将1个变量的值赋值给另外1个变量,例如

int x = 10;
int y = x; 
y = 20;

这表示上面的语句会在内存中的两个地方存储值10。这样直接更改y变量的值时,不会影响到x的值。

当使用引用类型,进行赋值的操作时,例如

List  listNum = new List();
listNum.add(1);
listNum.add(2);
listNum.add(3);
List listNum1 = listNum;
listNum.Clear();
listNum.Count;
listNum1.Count;

当我们访问两个变量的数量时,都为0。

记录一下C#深拷贝的几种方式_第1张图片

       首先,listNum和listNum1,都是引用类型的变量,它们都指向包含该内存的位置,引用类型变量的赋值,只保留了一个引用,因为两个变量都指向了一块内存地址,所以对两个变量中任何一个变量的操作都会影响到另外一个。

那么该怎么办呢?我们可以通过深拷贝的方式解决上面的问题。

通过以下几种方式,实现深拷贝。

1、最简单直接的是,循环变量赋值

private static List DeepCopyData(List list)
{
    //此处使用new关键字,创建了对象,所以该变量指向了个新的引用
    List listDeep = new List();
    for(var i=0;i

 因为在函数体中,直接创建了新的对象,在进行其他操作,就不会影响另外一个变量了。

2、通过JsonConvert,序列化和反序列化操作

 public static T DeepCopyJson(T obj)
 {
     // 序列化
     string json = JsonConvert.SerializeObject(obj);
     // 反序列化
     return JsonConvert.DeserializeObject(json);
 }

 3、通过XmlSerializer和内存流

private static T DeepCopyXml(T obj)
{
     object rel;
     using (MemoryStream ms = new MemoryStream())
      {
          XmlSerializer xml = new XmlSerializer(typeof(T));
          xml.Serialize(ms, obj);
          ms.Seek(0, SeekOrigin.Begin);
          rel = xml.Deserialize(ms);
          ms.Close();
      }
      return (T)rel;
}

4、通过BinaryFormatter和内存流

private static T DeepCopyBinary(T obj)
{
     object rel;
     using (MemoryStream ms = new MemoryStream())
     {
          BinaryFormatter bf = new BinaryFormatter();
          bf.Serialize(ms, obj);
          ms.Seek(0, SeekOrigin.Begin);
          rel = bf.Deserialize(ms);
          ms.Close();
     }
     return (T)rel;
}

5、通过DataContractSerializer和内存流

private static T DeepCopyDataContract(T obj)
{
     object rel;
     using(MemoryStream ms = new MemoryStream())
     {
          DataContractSerializer ser = new DataContractSerializer(typeof(T));
          ser.WriteObject(ms, obj);
          ms.Seek(0, SeekOrigin.Begin);
          rel = ser.ReadObject(ms);
          ms.Close();
     }
     return (T)rel;
}

你可能感兴趣的:(c#)