好像园内比较多博客对 Shallow、Deep Cloning的翻译是深拷贝、浅拷贝,当时我懵了,这个叫法怎么怪怪的。

就好像看军情观察室,台湾评论员,导弹叫飞弹。

至于它们的区别,一张图就可以解释。

这两个概念,经常对一些对象操作时,忘了自己使用的是shallow 还是deep,而搞到神经大条。

  MSDN的解释是:

Clone can be implemented either as a deep copy or a shallow copy.In a deep copy, all objects are duplicated; whereas, in a shallow copy, only the top-level objects are duplicated and the lower levels contain references.http://msdn.microsoft.com/zh-cn/library/system.icloneable.clone.aspx

Shallow copy by creating a new object, and then copying the nonstatic fields of the current object to the new object.If a field is a value type, a bit-by-bit copy of the field is performed.If a field is a reference type, the reference is copied but the referred object is not; therefore, the original object and its clone refer to the same object.http://msdn.microsoft.com/zh-cn/library/system.object.memberwiseclone.aspx

先说一下string,因为测试代码用了string对象:

string testClone = "a测试";
testClone = "b测试";
Console.WriteLine("testClone:" + testClone);
.entrypoint
// 代码大小 37 (0x25)
.maxstack
.locals init ([] string testClone)
IL_0000: nop
IL_0001: ldstr bytearray ( 4B 6D D5 8B ) // a.Km..
IL_0006: stloc.
IL_0007: ldstr bytearray ( 4B 6D D5 8B ) // b.Km..
IL_000c: stloc.
IL_000d: ldstr bytearray ( 6C 6F 6E // t.e.s.t.C.l.o.n.
1A FF ) // e...
IL_0012: ldloc.
IL_0013: call string [mscorlib]System.String::Concat(string,
string)
IL_0018: call void [mscorlib]System.Console::WriteLine(string)
IL_001d: nop
IL_001e: call int32 [mscorlib]System.Console::Read()
IL_0023: pop
IL_0024: ret

testClone = "b测试";创建了"b测试"对象,并将该对象指引赋值给 testClone;

String 对象称为不可变的(只读),因为一旦创建了该对象,就不能修改该对象的值。看来似乎修改了 String 对象的方法实际上是返回一个包含修改内容的新 String 对象。如果需要修改字符串对象的实际内容,请使用 System.Text.StringBuilder 类。

想查看IL指令,请看中英文对照表:

CN-http://www.cnblogs.com/flyingbirds123/archive/2011/01/29/1947626.html;

ES-http://en.csharp-online.net/CIL_Instruction_Set.

下面是我的测试代码:

CouponConfig couponClone = new CouponConfig() { Amount = , CouponName = "测试1", ListTest = new List<string> { "a", "b" } };
CouponConfig coupon1Clone = couponClone;
CouponConfig coupon2Clone = (CouponConfig)couponClone.Clone();
CouponConfig coupon3Clone = null; using (Stream objectStream = new MemoryStream())
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(objectStream, couponClone);
objectStream.Seek(, SeekOrigin.Begin);
coupon3Clone = (CouponConfig)formatter.Deserialize(objectStream);
}
couponClone.CouponName = "测试2";
coupon2Clone.ListTest.Add("c");
coupon3Clone.ListTest.Add("d"); Console.WriteLine("couponClone:" + couponClone.CouponName);
Console.WriteLine("coupon2Clone:" + coupon2Clone.CouponName);
foreach (string c in couponClone.ListTest)
{
Console.Write(c);
}
Console.WriteLine("");
foreach (string c in coupon2Clone.ListTest)
{
Console.Write(c);
}
Console.WriteLine("");
foreach (string c in coupon3Clone.ListTest)
{
Console.Write(c);
}
Console.WriteLine("");
Console.Read();
[Serializable]
public class CouponConfig : ICloneable
{ private CouponConfig config;
public CouponConfig Config
{
get
{
if (config == null)
{
config = null;
}
return config;
}
} public CouponConfig()
{ }
#region Model
private int _amount;
private string _couponname;
private List<string> listTest;
public string CouponName
{
get { return _couponname; }
set { _couponname = value; }
}
public List<string> ListTest
{
get { return listTest; }
set { listTest = value; }
}
public int Amount
{
set { _amount = value; }
get { return _amount; }
} #endregion Model public object Clone()
{
return this.MemberwiseClone();
}
}

运行结果是:

接下来思考一下吧,datatable的Copy、Clone是什么cloning呢?

DataTable dt = new DataTable();
DataTable dtcopy = dt.Copy();
DataTable dtclone = dt.Clone();

当然最常见的是Ling to sql 的操作,where、OrderBy···,是什么cloning呢?

对象类实现了ICloneable就可以使用this.MemberwiseClone(); 实现shallow cloning;

也可以自己写clone

public class Person : ICloneable
{
public string Name;
public Person Spouse;
public object Clone()
{
Person p = new Person();
p.Name = this.Name;
if (this.Spouse != null)
p.Spouse = (Person)this.Spouse.Clone();
return p;
}
}

Deep Cloning可以使用 Serialization

using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
public static class ObjectCopier
{
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
} // Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
} IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}

原文链接:http://www.cnblogs.com/daihuiquan/archive/2013/02/14/2910657.html

对C#对象的Shallow、Deep Cloning认识【转】的更多相关文章

  1. GC之二--GC是如何回收时的判断依据、shallow(浅) size、retained(保留) size、Deep(深)size

    回到问题“为何会内存溢出?”. 要回答这个问题又要引出另外一个话题,既什么样的对象GC才会回收? 一.对象存活方式判断方法 在上一篇文章<GC之一--GC 的算法分析.垃圾收集器.内存分配策略介 ...

  2. Java:浅克隆(shallow clone)与深克隆(deep clone)

    Summary 浅克隆与深克隆对于JavaSE来说,是个难度系数比较低的概念,但不应该轻视它. 假设一个场景:对于某个list,代码里并没有任何对其的直接操作,但里面的元素的属性却被改变了,这可能就涉 ...

  3. 《Beginning Java 7》 - 2 - Cloning 克隆

    Cloning 分两类:影子克隆 shallow cloning 深度克隆 deep cloning * 调用 clone() 需要 implments Cloneable.此函数为 protecte ...

  4. 《JavaScript 模式》读书笔记(5)— 对象创建模式2

    这一篇,我们主要来学习一下私有属性和方法以及模块模式. 三.私有属性和方法 JavaScript并没有特殊的语法来表示私有.保护.或公共属性和方法,在这一点上与Java或其他语言是不同的.JavaSc ...

  5. [Java基础] Java对象内存结构

    转载地址:http://www.importnew.com/1305.html 原文于2008年11月13日 发表, 2008年12月18日更新:这里还有一篇关于Java的Sizeof运算符的实用库的 ...

  6. net对象的克隆

    class Person { public string name; public List<string> hobby; } void main() { Person p1 = new ...

  7. JAVA Shallow heap & Retained heap

    最近在研究内存泄漏的问题,在使用MAT工具中发现了Shallow heap & Retained heap,不懂. 然后在网上找了一些资料. Shallow Size 对象自身占用的内存大小, ...

  8. Shallow Size 和 Retained Size

    所有包含Heap Profling功能的工具(MAT, Yourkit, JProfiler, TPTP等)都会使用到两个名词,一个是Shallow Size,另一个是 Retained Size. ...

  9. Java高效编程之二【对所有对象都通用的方法】

    对于所有对象都通用的方法,即Object类的所有非final方法(equals.hashCode.toString.clone和finalize)都有明确的通用约定,都是为了要被改写(override ...

随机推荐

  1. windows下安装mysql压缩包版[转]

    版本:5.6.17 1.将解压后的文件夹放到某个目录下,比如c:\software; 2.在环境变量中新建MYSQL_HOME=C:\software\mysql-5.6.17-winx64,然后在系 ...

  2. Java程序员的日常—— 《编程思想》关于类的使用常识

    Java虽然利用JVM,让程序员可以放心大胆的使用,可是仍然会出现内存泄露等问题.世上没有绝对的银弹,因此也不能完全把所有的任务都交给JVM,了解Java中的初始化与垃圾回收还是必不可少的知识. 关于 ...

  3. atitit.组件化事件化的编程模型--服务端控件(1)---------服务端控件与标签的关系

    atitit.组件化事件化的编程模型--服务端控件(1)---------服务端控件与标签的关系 1. 服务器控件是可被服务器理解的标签.有三种类型的服务器控件: 1 1.1. HTML 服务器控件  ...

  4. atitit.团队建设总结fx O622

    团队建设总结fx O622 大的title 2 建设团队文化 2 办公环境(3s+树+湖) 3 每人一个办公室 3 弹性工作制 3 重大的决定公投体制 3 每年一个kid经验日 3 做自己想到做的事. ...

  5. 微软BI 之SSIS 系列 - 通过设置 CheckPoints 检查点来增强 SSIS Package 流程的重用性

    开篇介绍 通常一个 ETL Package 是由多个控制流和数据流共同组成,有的时候 ETL 的步骤可能会比较多,整个流程执行下来的时间可能比较长.假设在 ETL Package 中包含5个Task, ...

  6. struts2从2.2.3升级到2.3.15.1步骤

    1. 删除以下jar包 asm-3.1.jar asm-commons-3.1.jar commons-beanutils-1.7.0.jar commons-fileupload-1.2.2.jar ...

  7. android: SQLite升级数据库

    如果你足够细心,一定会发现 MyDatabaseHelper 中还有一个空方法呢!没错,onUpgrade() 方法是用于对数据库进行升级的,它在整个数据库的管理工作当中起着非常重要的作用,可 千万不 ...

  8. 騰訊RTX的API開發,給RTX開個天窗

    好多人可能沒聽說RTX這個軟件,在此我簡單說明一下,這個軟件是騰訊為企業開發的一個內部聊天軟件,服務端不是在騰訊那邊,而是需要企業自己安裝到自己公司內部的服務器上,以供企業內部員工交流使用,功能和QQ ...

  9. [轉載]史上最强php生成pdf文件,html转pdf文件方法

    之前有个客户需要把一些html页面生成pdf文件,然后我就找一些用php把html页面围成pdf文件的类.方法是可谓是找了很多很多,什么html2pdf,pdflib,FPDF这些都试过了,但是都没有 ...

  10. [GO编程] GO入门语法基础

    学习一门语言,首先肯定是要熟悉他的语法,然后才可以进行编程开发,虽然本人使用过C++,.net等语言,不过对于GO的一些新特性还是需要多多熟悉,否则即使看得懂也写不出程序来.今天我们就开始我们的GO ...