在我们进行赋值等其他运算操作时经常会遇到两种情况,浅复制和复制。
由于值类型的数据直接保存的数据的值,所以不涉及到深复制和浅复制的区别。当数据为引用类型时,直接声明一个类型并赋值是其实是进行了浅复制,只是复制了引用这时两个变量指向了同一个对象,其中一个对象值改变另一个也会改变,但是我想复制出来的类型独立于原来的类型呢。这时就必须利用深复制,不仅复制引用还要复制一个类型的副本。
实现深复制的两种方式
1.利用反射 通过反射拿到引用类型的类型并创建一个实例,将原来的数据赋值给信创建的实例 上代码
class Program
{
static void Main(string[] args)
{
Person P = new Person("小红",10);
Person n = (Person)DeepCopy(P);
P.Grade = 100;
Console.WriteLine(n.Grade.ToString());
Console.ReadKey();
}
/* 利用反射实现深拷贝
*/
public static object DeepCopy(object _object)
{
Type T = _object.GetType();
object o = Activator.CreateInstance(T);
PropertyInfo[] PI = T.GetProperties();
for (int i = 0; i < PI.Length; i++)
{
PropertyInfo P = PI[i];
P.SetValue(o,P.GetValue(_object));
}
return o;
}
}
class Person
{
private string mName;
private int mGrade;
public int Grade
{
get { return mGrade; }
set { mGrade = value; }
}
public string Name
{
get { return mName; }
set { mName = value; }
}
public Person(string _Name,int _Grade)
{
mName = _Name;
mGrade = _Grade;
}
public Person()
{
}
}
需要引用System.Reflection命名空间包含反射
我将两个类写在了同一个文件中,如果在不同文件可以用反射获取程序集或者加载Dll的方式进行
2.利用二进制序列化的方式进行深拷贝 有一个缺陷 序列化的类型必须标识为刻序列化的[Serializable] 否则无法进行二进制序列化
class Program
{
static void Main(string[] args)
{
Person P = new Person("小丽",20);
Person N = (Person)DeepCopy(P);
P.Grade = 200;
Console.WriteLine(N.Grade.ToString());
Console.ReadKey();
}
/// <summary>
/// 利用序列化实现深拷贝
/// </summary>
/// <param name="_obj"></param>
/// <returns></returns>
static object DeepCopy(object _obj)
{
BinaryFormatter BF2 = new BinaryFormatter();
using (MemoryStream stream = new MemoryStream())
{
BF2.Serialize(stream,_obj);
stream.Position = 0;
return BF2.Deserialize(stream);
}
}
}
[Serializable]
class Person
{
private string mName;
private int mGrade;
public int Grade
{
get { return mGrade; }
set { mGrade = value; }
}
public string Name
{
get { return mName; }
set { mName = value; }
}
public Person(string _Name, int _Grade)
{
mName = _Name;
mGrade = _Grade;
}
public Person()
{
}
}