1.基本的概念:

首先我们应该了解一下什么叫深拷贝与浅拷贝(Deep Copy and Shallow Copy)。

a.浅拷贝(Shallow Copy影子克隆):只复制对象的基本类型,对象类型,仍属于原来的引用。

b.深拷贝(Deep Copy 深度克隆):不紧复制对象的基本类,同时也复制原对象中的对象.完全产生新对象。

深拷贝与浅拷贝不同的是对于引用拷贝的处理,深拷贝将会在新对象中创建和原是对象中对应值类型的字段并且赋值。浅拷贝不会创建新引用类型,会返回相同的类 型引用。深拷贝会重新创建新对象,返回新对象的引用字。

2.深拷贝与浅拷贝实现机制:

从上面的概念我们了解了C#深拷贝与浅拷贝(Deep Copy and Shallow Copy)的不同之处。这个也就决定了两者有不同的实现方式。

对于值类型:

a.浅拷贝: 通过赋值等操作直接实现,将对象中的值类型的字段拷贝到新的对象中。
b.深拷贝:通过赋值等操作直接实现,将对象中的值类型的字段拷贝到新的对象中。 和浅拷贝相同

对于引用类型:

a.浅拷贝: MemberwiseClone 方法创建一个浅副本,方法是创建一个新对象,如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用原始对象,与原对象引用同一对象。

b.深拷贝:拷贝对象应用,也拷贝对象实际内容,也就是创建了一个新的改变新对象 不会影响到原始对象的内容
这种情况需要为其实现ICloneable接口中提供的Clone方法。

差别就是在对于引用类型的实现深拷贝和浅拷贝的时候的机制不同,前者是MemberwiseClone 方法实现,后者是通过继承实现ICloneable接口中提供的Clone方法,实现对象的深入拷贝。

3.代码实现

浅拷贝实例:

C# 代码   复制


using System;



namespace Prototype_Shallow{

//因为我们在FCL里面已经有这样的接口所以我们就不定义新的Prototype了

public class ConcretePrototype1 : ICloneable{

private int m_ID;

public int ID{

get{

return this.m_ID;

}

}

public ConcretePrototype1(int id){

this.m_ID = id;

}



public object Clone(){

return this.MemberwiseClone();

}

}



public class ConcretePrototype2 : ICloneable{

private int m_ID;

public int ID

{

get

{

return this.m_ID;

}

}

public ConcretePrototype2(int id){

this.m_ID = id;

}

public object Clone(){

return this.MemberwiseClone();

}

}



}

代码说明:

我们具体的原型都继承了接口ICloneable,同时也实现了该接口里面唯一个一个方法Clone。我们可以在客户端这样创建对象ConcretePrototype1 p1 = new ConcretePrototype1(1);

ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone();

首先我们创建了对象p1,接下来我们用通过p1的科隆方法得到了对象c1,这就是一种浅拷贝(因为MemberwiseClone是浅拷贝)。

深拷贝实例:

 
C# 代码   复制

namespace Prototype_Deep{

using System.Collections;

public class ConcretePrototype : ICloneable

{

private int m_ID;

public int ID

{

get

{

return this.m_ID;

}

}



private ArrayList m_arrayList = new ArrayList();



public ConcretePrototype(int id)

{

this.m_ID = id;

this.m_arrayList.Add("FirstObject");

this.m_arrayList.Add("SecondObject");

// ...

}



public object Clone()

{

ConcretePrototype c = new ConcretePrototype(this.ID);

c.m_arrayList = new ArrayList();

c.m_arrayList.Add("FirstObject");

c.m_arrayList.Add("SecondObject");

return c;

}



public ConcretePrototype DeepClone(){

return (ConcretePrototype)this.Clone();

}

}

}

代码说明:

该代码显示了如何实现深拷贝,深拷贝的原则就是对于那些引用的字段您需要new(new之前想想是不是能用前面学过的某个创建型的模式实现,这是一个好的习惯)一个出来,然后对该字段里面的对象一一拷贝,这样以来很容易出现循环拷贝,所以说深拷贝要比浅拷贝更难一些。

客户端可以通过

ConcretePrototype p = new ConcretePrototype(1);

ConcretePrototype c = p.DeepClone();

来实现克隆一个新的对象。

C#中的深拷贝与浅拷贝的更多相关文章

  1. 浅谈Java中的深拷贝和浅拷贝(转载)

    浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...

  2. C语言中的深拷贝和浅拷贝

    //C语言中的深拷贝和浅拷贝 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #inc ...

  3. 浅谈Java中的深拷贝和浅拷贝

    转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...

  4. 内功心法 -- Java中的深拷贝和浅拷贝

    写在前面的话:读书破万卷,编码如有神--------------------------------------------------------------------这篇博客主要来谈谈" ...

  5. **Python中的深拷贝和浅拷贝详解

    Python中的深拷贝和浅拷贝详解   这篇文章主要介绍了Python中的深拷贝和浅拷贝详解,本文讲解了变量-对象-引用.可变对象-不可变对象.拷贝等内容.   要说清楚Python中的深浅拷贝,需要 ...

  6. javascript中的深拷贝与浅拷贝

    javascript中的深拷贝与浅拷贝 基础概念 在了解深拷贝与浅拷贝的时候需要先了解一些基础知识 核心知识点之 堆与栈 栈(stack)为自动分配的内存空间,它由系统自动释放: 堆(heap)则是动 ...

  7. JavaScript中的深拷贝和浅拷贝!【有错误】还未修改!请逛其他园子!

    JavaScript中的深拷贝和浅拷贝! 浅拷贝 1.浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用.{也就是拷贝的是地址!简而言之就是在新的对象中修改深层次的值也会影响原来的对象!} // 2.深 ...

  8. 001 说说Python中的深拷贝和浅拷贝

    在Python编程中忽略深拷贝和浅拷贝可能会造成未知的风险. 比如我们打算保存一份原始对象的副本作为上一状态的记录,此后修改原始对象数据时,若是副本对象的数据也发生改变,那么这就是一个严重的错误. 注 ...

  9. Objective-C中的深拷贝和浅拷贝

    在Objective-C中对象之间的拷贝分为浅拷贝和深拷贝.说白了,对非容器类的浅拷贝就是拷贝对象的地址,对象里面存的内容仍然是一份,没有新的内存被分配.对非容器类的深拷贝就是重写分配一块内存,然后把 ...

  10. python中的深拷贝与浅拷贝

    深拷贝和浅拷贝 浅拷贝的时候,修改原来的对象,浅拷贝的对象不会发生改变. 1.对象的赋值 对象的赋值实际上是对象之间的引用:当创建一个对象,然后将这个对象赋值给另外一个变量的时候,python并没有拷 ...

随机推荐

  1. 第10条:始终要覆盖toString

    java.lang.Object的toString方法的实现: public String toString() { return getClass().getName() + "@&quo ...

  2. 【转】Ubuntu编译安装mysql源码

    主要参考了下面两篇文章 http://forum.ubuntu.org.cn/viewtopic.php?t=330121 http://www.linuxidc.com/Linux/2011-09/ ...

  3. linux系统使用密钥登录设置

    使用密钥登录linux的操作步骤(使用putty): 1.用putty远程登录linux服务器,然后使用puttygen生成密钥,将生成的密钥保存,保存私钥将公钥复制保存到linux服务器的autho ...

  4. poj 2533 Longest Ordered Subsequence 最长递增子序列

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4098562.html 题目链接:poj 2533 Longest Ordered Subse ...

  5. think完全还原原形的 SQL

    $dd     =   Db::getInstance(); //实例连接数据库$sql = "SELECT * FROM `yezi_friendlinks`"; // SQL$ ...

  6. memcached 在windows下安装及启动

    memcached 在windows下安装及启动   Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数, ...

  7. Asp.net Gridview导出Excel

    前台页面放一个GridView什么的就不说了,要注意的是在 <%@ Page Language="C#" AutoEventWireup="true" C ...

  8. PHP常见算法-面试篇(2)

    1.顺序查找 思路分析: 从数组的第一个元素开始一个一个向下查找,如果有和目标一致的元素,查找成功:如果到最后一个元素仍没有目标元素,则查找失败. 代码实现: <?php function se ...

  9. codeforce #339(div2)C Peter and Snow Blower

    Peter and Snow Blower 题意:有n(3 <= n <= 100 000)个点的一个多边形,这个多边形绕一个顶点转动,问扫过的面积为多少? 思路:开始就认为是一个凸包的问 ...

  10. cocos2dx伸缩式列表效果

    效果: 代码: ElasticListView.h #pragma once //std #include <string> #include <map> //cocos #i ...