博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# 浅拷贝与深拷贝区别 解惑篇
阅读量:7128 次
发布时间:2019-06-28

本文共 3198 字,大约阅读时间需要 10 分钟。

问题起源:

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

曾经的以为:

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

同事的质问:

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

引申出的错乱:

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

 

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

ExpandedBlockStart.gif
    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
string
int[]
string[]
enum
struct
class
然后接下来会产生实例A和克隆实例B。
接着改变B的值,看A的值会不会被改变。

 

接下我们看main方法

ExpandedBlockStart.gif
        
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();
}

 

接着我们写示例代码比较:

ExpandedBlockStart.gif
        
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最后还得对类型转换进行一些开销,教人情何以堪!

 

附言:

这两天刚好感冒,插了这两篇解惑篇,都是临时插进来的的问题了,接下来会继续写  框架 的相关文章。

 

转载地址:http://hsrel.baihongyu.com/

你可能感兴趣的文章
我的友情链接
查看>>
parted解决超大容量磁盘分区 GPT分区表
查看>>
我的友情链接
查看>>
深入浅出JSONP--解决ajax跨域问题
查看>>
2014-02-23,LAMP-ThinkPHP听课笔记
查看>>
oracle 脚本(1)-清空当前用户下所有表的数据
查看>>
即可去除桌面图标阴影
查看>>
BlockingQueue详解
查看>>
SVN入门及配置使用
查看>>
Java IO类库之ByteArrayOutputStream
查看>>
《Spring5学习》04 - 面向切面编程
查看>>
druid简单教程
查看>>
推荐一款免费好用的网页视频播放器
查看>>
Android 保活
查看>>
小程序环境搭建与开发工具的简单介绍
查看>>
我的友情链接
查看>>
red hat5安装mysql5.5.25
查看>>
深入理解C++的动态绑定和静态绑定
查看>>
cisco 7200 simulator
查看>>
JAVA WEB搭建 SpringMVC+Spring+hibernate 框架
查看>>