C#浅拷贝与深拷贝区别解析

C#浅拷贝与深拷贝区别解析,第1张

  今天我们谈谈C#中的对象拷贝问题;

  所谓的对象拷贝,其实就是为对象创建副本,C#中将拷贝分为两种,分别为浅拷贝深拷贝

  所谓浅拷贝就是将对象中的所有字段复制到新的副本对象中;浅拷贝对于值类型与引用类型的方式有区别,值类型字段的值被复制到副本中后,在副本中的修改不会影响源对象对应的值;然而对于引用类型的字段被复制到副本中的却是引用类型的引用,而不是引用的对象,在副本中对引用类型的字段值被修改后,源对象的值也将被修改。

  深拷贝也同样是将对象中的所有字段复制到副本对象中,但是,无论对象的值类型字段或者引用类型字段,都会被重新创建并复制,对于副本的修改,不会影响到源对象的本身;

  当然,无论是哪种拷贝,微软都建议使用类型继承ICloneable接口的方式明确告诉调用者,该对象是否可用被拷贝。当然了,ICloneable接口只提供了一个声明为Clone的方法,我们可以根据需求在Clone的方法内实现浅拷贝或者是深拷贝

  浅拷贝和深拷贝的区别

  浅拷贝是指将对象中的数值类型的字段拷贝到新的对象中,而对象中的引用型字段则指复制它的一个引用到目标对象。如果改变目标对象 中引用型字段的值他将反映在原是对象中,也就是说原始对象中对应的字段也会发生变化。深拷贝与浅拷贝不同的是对于引用的处理,深拷贝将会在新对象中创建一 个新的和原是对象中对应字段相同(内容相同)的字段,也就是说这个引用和原是对象的引用是不同的,我们在改变新对象中的这个字段的时候是不会影响到原始对 象中对应字段的内容。所以对于原型模式也有不同的两种处理方法:对象的浅拷贝和深拷贝。

  深浅拷贝的几种实现方式

  上面已经明白了深浅拷贝的定义,至于他们之间的区别也在定义中也有所体现。介绍完了它们的定义和区别之后,自然也就有了如何去实现它们呢?

  对于,浅拷贝的实现方式很简单,.NET自身也提供了实现。我们知道,所有对象的父对象都是System.Object对象,这个父对象中有一个MemberwiseClone方法,该方法就可以用来实现浅拷贝,下面具体看看浅拷贝的实现方式,具体演示代码如下所示:

  // 继承ICloneable接口,重新其Clone方法

  class ShallowCopyDemoClass : ICloneable

  {

  public int intValue = 1;

  public string strValue = “1”;

  public PersonEnum pEnum = PersonEnum.EnumA;

  public PersonStruct pStruct = new PersonStruct() { StructValue = 1};

  public Person pClass = new Person(“1”);

  public int[] pIntArray = new int[] { 1 };

  public string[] pStringArray = new string[] { “1” };

  #region ICloneable成员

  public object Clone()

  {

  return this.MemberwiseClone();

  }

  #endregion

  }

  class Person

  {

  public string Name;

  public Person(string name)

  {

  Name = name;

  }

  }

  public enum PersonEnum

  {

  EnumA = 0,

  EnumB = 1

  }

  public struct PersonStruct

  {

  public int StructValue;

  }

  上面类中重写了IConeable接口的Clone方法,其实现直接调用了Object的MemberwiseClone方法来完成浅拷贝,如果想实现深拷贝,也可以在Clone方法中实现深拷贝的逻辑。接下来就是对上面定义的类进行浅拷贝测试了,看看是否是实现的浅拷贝,具体演示代码如下所示:

  class Program

  {

  staTIc void Main(string[] args)

  {

  ShallowCopyDemo();

  // List浅拷贝的演示

  ListShallowCopyDemo();

  }

  public staTIc void ListShallowCopyDemo()

  {

  List《PersonA》 personList = new List《PersonA》()

  {

  new PersonA() { Name=“PersonA”, Age= 10, ClassA= new A() { TestProperty = “AProperty”} },

  new PersonA() { Name=“PersonA2”, Age= 20, ClassA= new A() { TestProperty = “AProperty2”} }

  };

  // 下面2种方式实现的都是浅拷贝

  List《PersonA》 personsCopy = new List《PersonA》(personList);

  PersonA[] personCopy2 = new PersonA[2];

  personList.CopyTo(personCopy2);

  // 由于实现的是浅拷贝,所以改变一个对象的值,其他2个对象的值都会发生改变,因为它们都是使用的同一份实体,即它们指向内存中同一个地址

  personsCopy.First().ClassA.TestProperty = “AProperty3”;

  WriteLog(string.Format(“personCopy2.First().ClassA.TestProperty is {0}”, personCopy2.First().ClassA.TestProperty));

  WriteLog(string.Format(“personList.First().ClassA.TestProperty is {0}”, personList.First().ClassA.TestProperty));

  WriteLog(string.Format(“personsCopy.First().ClassA.TestProperty is {0}”, personsCopy.First().ClassA.TestProperty));

  Console.Read();

  }

  public staTIc void ShallowCopyDemo()

  {

  ShallowCopyDemoClass DemoA = new ShallowCopyDemoClass();

  ShallowCopyDemoClass DemoB = DemoA.Clone() as ShallowCopyDemoClass ;

  DemoB.intValue = 2;

  WriteLog(string.Format(“ int-》[A:{0}] [B:{1}]”, DemoA.intValue, DemoB.intValue));

  DemoB.strValue = “2”;

  WriteLog(string.Format(“ string-》[A:{0}] [B:{1}]”, DemoA.strValue, DemoB.strValue));

  DemoB.pEnum = PersonEnum.EnumB;

  WriteLog(string.Format(“ Enum-》[A: {0}] [B:{1}]”, DemoA.pEnum, DemoB.pEnum));

  DemoB.pStruct.StructValue = 2;

  WriteLog(string.Format(“ struct-》[A: {0}] [B: {1}]”, DemoA.pStruct.StructValue, DemoB.pStruct.StructValue));

  DemoB.pIntArray[0] = 2;

  WriteLog(string.Format(“ intArray-》[A:{0}] [B:{1}]”, DemoA.pIntArray[0], DemoB.pIntArray[0]));

  DemoB.pStringArray[0] = “2”;

  WriteLog(string.Format(“stringArray-》[A:{0}] [B:{1}]”, DemoA.pStringArray[0], DemoB.pStringArray[0]));

  DemoB.pClass.Name = “2”;

  WriteLog(string.Format(“ Class-》[A:{0}] [B:{1}]”, DemoA.pClass.Name, DemoB.pClass.Name));

  Console.WriteLine();

  }

  private staTIc void WriteLog(string msg) { Console.WriteLine(msg); }   } }

  上面代码的运行结果如下图所示:

  C#浅拷贝与深拷贝区别解析,C#浅拷贝与深拷贝区别解析,第2张

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/dianzi/2717496.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-08-17
下一篇 2022-08-17

发表评论

登录后才能评论

评论列表(0条)

保存