深拷贝与浅拷贝
- 值类型(value type):byte,short,int,long,float,double,decimal,char,bool 和 struct 统称为值类型。值类型变量声明后,不管是否已经赋值,编译器为其分配内存。
- 引用类型(reference type):string 和 class统称为引用类型。当声明一个类时,只在栈中分配一小片内存用于容纳一个地址,而此时并没有为其分配堆上的内存空间。当使用 new 创建一个类的实例时,分配堆上的空间,并把堆上空间的地址保存到栈上分配的小片空间中。
- 值类型的拷贝简单又直接,但是引用类型的拷贝分为浅拷贝和深拷贝,浅拷贝的本质其实是指向同一个地址的两个引用,改变其中任意一个,另一个都会发生改变,浅拷贝不会开辟新的内存空间。深拷贝是完全独立于原来的地址,重新分配了一块内存,将原来内存的数据拷贝一份,改变其中任意一个,另一个不受影响。
- 利用 System.Runtime.Serialization序列化与反序列化可以简单有效的完成深拷贝的工作。
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace 深拷贝与浅拷贝
{
[Serializable]
class MyPoint
{
public double x;
public double y;
public double z;
public double r;
public MyPoint()
{
x = 0;
y = 0;
z = 0;
r = 0;
}
public static T Copy<T>(T RealObject)
{
using (Stream objectStream = new MemoryStream())
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(objectStream, RealObject);
objectStream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(objectStream);
}
}
}
[Serializable]
class Program
{
static void Main(string[] args)
{
List<MyPoint> myPointList1 = new List<MyPoint>();
MyPoint p = new MyPoint();
for (int i = 0; i < 20; i++)
{
myPointList1.Add(p);
}
List<MyPoint> myPointList2 = new List<MyPoint>();
myPointList2 = myPointList1;
myPointList1[10].x = 100;
Console.WriteLine(myPointList1[10].x.ToString());
Console.WriteLine(myPointList2[10].x.ToString());
List<MyPoint> myPointList3 = MyPoint.Copy(myPointList1);
myPointList1[10].x = 0;
Console.WriteLine(myPointList1[10].x.ToString());
Console.WriteLine(myPointList3[10].x.ToString());
}
}
}