前言:
MemberwiseClone是C#中Object中的成员方法
该方法用于获取对象的浅拷贝对象,可以简单理解为返回一个新的对象。
一:在使用MemberwiseClone时,被拷贝的内容可以分为两类
(1):字段为值类型
若字段为值类型,则会原封不动的拷贝并粘贴过去,且新对象与原对象的值类型互相独立,互不干扰,其中一个修改,另一个置之不理,不做修改!
(2):字段为引用类型
若字段为引用类型,那么新对象则是复制老对象中引用类型的引用,而不是被引用的对象,可以简单理解为新老对象是引用同一对象的,一方的引用对象中的内容修改,另一方也会跟着变化,但是并不是两个对象而是二者公用一个对象!
(3)注意:
对于我个人的理解即使是引用类型的string类型好像是被当成了值类型作为处理,即也是各自管理各自的!
(若还是不懂可以参考代码和本人自己所绘制的拙劣示意图)
二:代码演示
namespace MemberwiseClone
{
class MonsterId
{
public int Id;
public MonsterId(int Id) { this.Id = Id; }
}
class Monster
{
public int Hp;
public string Name;
public MonsterId monsterId;
public Monster ShallowCopy()
{
return (Monster)MemberwiseClone();
}
}
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("MemberwiseClone浅拷贝");
Console.WriteLine("----------------------");
Monster m1 = new()
{
Hp = 100,
Name = "Goblin One",
monsterId = new MonsterId(1)
};
Console.WriteLine("怪物m1创建完毕,信息如下");
Console.WriteLine("HP={0},Name={1},Id={2}",m1.Hp,m1.Name,m1.monsterId.Id);
Monster m2 = m1.ShallowCopy();
Console.WriteLine();
Console.WriteLine("怪物m2由怪物m1浅拷贝而拷贝完成,信息如下");
Console.WriteLine("Hp={0},Name={1},Id={2}",m2.Hp,m2.Name,m2.monsterId.Id);
Console.WriteLine("-------------------------------------------------------------------");
//对值类型进行修改(string)
m1.Hp = 200;
m1.Name = "Goblin Two";
m2.Hp = 300;
m2.Name = "Goblin Three";
Console.WriteLine("HP={0},Name={1},Id={2}", m1.Hp, m1.Name, m1.monsterId.Id);
Console.WriteLine("Hp={0},Name={1},Id={2}", m2.Hp, m2.Name, m2.monsterId.Id);
Console.WriteLine("-------------------------------------------------------------------");
//对引用类型进行修改
m1.monsterId.Id = 123;
Console.WriteLine("HP={0},Name={1},Id={2}", m1.Hp, m1.Name, m1.monsterId.Id);
Console.WriteLine("Hp={0},Name={1},Id={2}", m2.Hp, m2.Name, m2.monsterId.Id);
Console.WriteLine("-------------------------------------------------------------------");
m2.monsterId.Id = 123123;
Console.WriteLine("HP={0},Name={1},Id={2}", m1.Hp, m1.Name, m1.monsterId.Id);
Console.WriteLine("Hp={0},Name={1},Id={2}", m2.Hp, m2.Name, m2.monsterId.Id);
//总结:
//可以看到在修改值类型时m1,m2各自管理各自的值类型(包括string)成员
//但是在修改其中一方的引用类型成员时,另一方也会同步,这是因为二者的引用一致,二者指向同一地址
}
}
}
运行结果如下:
三:总结
(1):正如上述所示,这就是在利用浅拷贝时值类型和引用类型的区别!
(2):另外对于浅拷贝而言,我们还可以封装新的Clone方法利用MemberwiseClone()中的处理,再加上一些特殊逻辑处理完善克隆复制的操作!