C# 浅拷贝与深拷贝区别 解惑篇

网友投稿 738 2022-12-02

C# 浅拷贝与深拷贝区别 解惑篇

C# 浅拷贝与深拷贝区别 解惑篇

昨天被同事问到一个浅拷贝与深拷贝区别的问题,说实在的,记得在学校时在书在看过相关概念区别。只是,那时的在校生,又有几个能对书本上那写的尽量让鬼都看不懂知识能清晰的理解呢。工作后虽然也有用到Clone相关的内容,不过也仅是应用,基础的概念还是没去仔细的理解,以于后来DataTable内部那不深不浅的架构拷贝都混和这些概念混在一起了。

曾经的以为:

让得一年多以前,我去面试,被一个人问到浅拷贝与深拷贝区别,我答:浅拷贝就是拷贝就是拷贝架构,不包括值,深拷贝就是连值也一同拷贝。当我答出这样错误的答案时,对方没有纠正,反而似乎对我的答案还挺满意的。唉,面试管自己不懂还问我这问题,还让我一直以为到现在都是这个样。

同事的质问:

接着同事说它的示例里,发现值是有拷贝的,于是我意识到我的认知是有问题了,我重新百度了一下。网上乱七杂八的答案,让我得一个模糊的似乎正确的答案:浅拷贝不拷贝内部类的对象

引申出的错乱:

接着同事的疑问更一度把我引向这个容易迷乱的错误深渊:浅拷贝是对引用类型拷贝地址,对值类型直接进行拷贝。

最后,为了解惑,还是用示例来说话了:

class DemoClass : ICloneable { public int intValue = 1; public string strValue = "1"; public PersonEnum pEnum = PersonEnum.EnumA; public PersonStruct pStruct = new PersonStruct(); public Person pClass = new Person("1"); public int[] pIntArray = new int[] { 1 }; public string[] pArray = new string[] { "1" }; #region ICloneable 成员 public DemoClass() { pStruct.StructValue = 1; } public object Clone() { return this.MemberwiseClone(); } #endregion } class Person { public string Name; public Person(string name) { Name = name; } } public enum PersonEnum { EnumA=1, EnumB=2 } public struct PersonStruct { public int StructValue; } 说明: 这里的示例,我用上了:intstring int[]string[]enumstructclass然后接下来会产生实例A和克隆实例B。接着改变B的值,看A的值会不会被改变。 接下我们看main方法 static void Main( string [] args) { Demo(); } public static void Demo() { DemoClass A = new DemoClass(); DemoClass B = (DemoClass)A.Clone(); B.intValue = 2 ; Write( string .Format( " int->[A:{0}] [B:{1}] " , A.intValue, B.intValue)); B.strValue = " 2 " ; Write( string .Format( " string->[A:{0}] [B:{1}] " , A.strValue, B.strValue)); B.pEnum = PersonEnum.EnumB; Write( string .Format( " Enum->[A:{0}] [B:{1}] " , ( int )A.pEnum, ( int )B.pEnum)); B.pStruct.StructValue = 2 ; Write( string .Format( " struct->[A:{0}] [B:{1}] " , A.pStruct.StructValue, B.pStruct.StructValue)); B.pIntArray[ 0 ] = 2 ; Write( string .Format( " intArray->[A:{0}] [B:{1}] " , A.pIntArray[ 0 ], B.pIntArray[ 0 ])); B.pStringArray[ 0 ] = " 2 " ; Write( string .Format( " stringArray->[A:{0}] [B:{1}] " , A.pStringArray[ 0 ], B.pStringArray[ 0 ])); B.pClass.Name = " 2 " ; Write( string .Format( " Class->[A:{0}] [B:{1}] " , A.pClass.Name, B.pClass.Name)); System.Console.Read(); } static void Write( string msg) { System.Console.WriteLine(msg); } 说明: 我们通过改变B实例的值,然后打印出A和B的值看结果。 打印结果如下:从最后输出的结果我们得知: 对于内部的Class的对象和数组,会Copy地址一份。[从而改变B时,A也被改变了] 而对于其它内置的int/string/Enum/struct/object类型,则进行值copy。 最后,我试着百度寻找浅拷贝最原生的定义,浅搜了一下找不到,那这个定义,就留给读者解答一下了。 接着,我顺手比较了一下浅拷贝和深拷贝的性能测试:先在DemoClass加入一个函数: public object CloneNew(){ return new DemoClass();} 接着我们写示例代码比较: public static void Compare() { DemoClass baseClass = new DemoClass(); DateTime start = DateTime.Now; for ( int i = 0 ; i < 1000000 ; i ++ ) { DemoClass newClass = (DemoClass)baseClass.Clone(); } TimeSpan ts = DateTime.Now - start; System.Console.WriteLine( " 浅拷贝: " + ts.Ticks); DateTime start2 = DateTime.Now; for ( int j = 0 ; j < 1000000 ; j ++ ) { DemoClass newClass = (DemoClass)baseClass.CloneNew(); } TimeSpan ts2 = DateTime.Now - start2; System.Console.WriteLine( " 深拷贝: " + ts2.Ticks); System.Console.Read(); }

最后得出结果:

看来直接用浅拷贝性能还不如直接返回一个new的对象。

同样的,用克隆返回object最后还得对类型转换进行一些开销,教人情何以堪!

附言:

这两天刚好感冒,插了这两篇解惑篇,都是临时插进来的的问题了,接下来会继续写 ​​CYQ.Data 轻量数据层之路​​ 框架 的相关文章。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:一条SQL语句求全年平均值
下一篇:SpringBoot 进行限流的操作方法
相关文章

 发表评论

暂时没有评论,来抢沙发吧~