摘要
复制一直是面试喜欢问的问题,这里总结一下
浅复制与深复制
-
浅copy:只复制引用,修改后对原来的变量有影响。
-
深copy:复制引用和引用的对象,修改后对原来的变量没有影响
=
复制
浅复制
-
值类型:复制值,修改后对原来的变量没有影响
-
引用类型:复制引用地址,修改后对原来的变量有影响
-
String: 跟着值类型走
MemberwiseClone
浅复制
Object
的实例方法MemberwiseClone
实现的是浅复制,注意是protected修饰,只能定义的继承类或者extension实现
protected Object MemberwiseClone();
深copy实现
-
反射
-
序列化反序列化,最简单
-
实现ICloneable接口Clone方法,手工复制对象的每一个field
通用实现
序列化
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace DotnetDemo
{
[Serializable]
public class BaseClone<T>
{
public virtual T Clone()
{
using (var memoryStream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(memoryStream, this);
memoryStream.Position = 0;
return (T)formatter.Deserialize(memoryStream);
}
}
}
}
实现的demo
注意必须为相关类及类的引用类型加上可序列化标识:[Serializable]
using System;
namespace DotnetDemo
{
public class CloneDemo
{
public void Test()
{
// 值类型
var aa = 11;
var bb = aa;
bb = 22;
Console.WriteLine(aa); //11
// string
var cc = "11";
var dd = cc;
dd = "22";
Console.WriteLine(cc); //"11"
// 引用类型
var ee = new CloneDemoInfo() { ID = 11, ExtensionInfo = new ExtensionInfo() { Name = "Name" } };
var ff = ee;
var gg = ee.ShallowCopy();
ff.ID = 22;
ff.ExtensionInfo = new ExtensionInfo() { Name = "newName" };
Console.WriteLine(ee.ID); // 22
Console.WriteLine(ee.ExtensionInfo.Name); // newName
var hh = ee.Clone();
hh.ID = 33;
hh.ExtensionInfo = new ExtensionInfo() { Name = "CloneName" };
Console.WriteLine(ee.ID); // 22
Console.WriteLine(ee.ExtensionInfo.Name); // newName
}
}
[Serializable]
public class ExtensionInfo
{
public string Name { get; set; }
}
[Serializable]
public class CloneDemoInfo : BaseClone<CloneDemoInfo>
{
public int ID { get; set; } //值类型
public ExtensionInfo ExtensionInfo { get; set; } //引用类型
/// <summary>
/// 浅复制
/// </summary>
/// <returns></returns>
public CloneDemoInfo ShallowCopy()
{
return (CloneDemoInfo)this.MemberwiseClone();
}
}
}