一年多以前,我去面试,被一个人问到浅拷贝与深拷贝区别,我答:浅拷贝就是拷贝就是拷贝架构,不包括值,深拷贝就是连值也一同拷贝。
当我答出这样错误的答案时,对方没有纠正,反而似乎对我的答案还挺满意的。
唉,面试管自己不懂还问我这问题,还让我一直以为到现在都是这个样。
同事的质问:
接着同事说它的示例里,发现值是有拷贝的,于是我意识到我的认知是有问题了,我重新百度了一下。
网上乱七杂八的答案,让我得一个模糊的似乎正确的答案:浅拷贝不拷贝内部类的对象
引申出的错乱:
接着同事的疑问更一度把我引向这个容易迷乱的错误深渊:浅拷贝是对引用类型拷贝地址,对值类型直接进行拷贝。
最后,为了解惑,还是用示例来说话了:
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; }
说明:
这里的示例,我用上了: int stringint[] string[] enum struct class 然后接下来会产生实例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最后还得对类型转换进行一些开销,教人情何以堪!
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦