好像园内比较多博客对 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. C++ 标准IO库

    <C++ Primer 4th>读书笔记 C++ 的输入/输出(input/output)由标准库提供.标准库定义了一族类型,支持对文件和控制窗口等设备的读写(IO).还定义了其他一些类型 ...

  2. Lucene.net入门学习(结合盘古分词)

    Lucene简介 Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整 ...

  3. Cocos2d-JS V3.10 一个小bug提示

    感谢读者古事东流反馈,新版V3.10的音乐播放接口存在一个bug. 重复播放一个音乐,会出现音乐停止的状况. debug了一下,发现src的对比有点问题.传入的url是相对路径,但背景bgMusic. ...

  4. 如何安装、配置Apache

    Apache的安装流程网上版本很多,但很多版本有错误,或者缺漏,如果初学者按照那样安装的话会遇到各种各样的问题.我整理了自己安装.配置Apache的过程,亲测有效,分享给大家. 基本过程如下: Dow ...

  5. jQuery 之父:每天写代码

    去年秋天我的支线代码项目 遇到了一些问题,项目进展不足,而且我没法找到一个完成更多代码的方法(在不影响我在Khan Academy方面的工作的前提下). 我主要在周末进行我的支线,当然有时候也在晚上进 ...

  6. 关于PF_RING/Intel 82599/透明VPN的一些事

    接近崩溃的边缘,今天这篇文章构思地点在医院,小小又生病了,宁可吊瓶不吃药,带了笔记本却无法上网,我什么都不能干,想了解一些东西,只能用3G,不敢 开热点,因为没人给我报销流量,本周末我只有一天时间,因 ...

  7. python coroutine测试

    目的:实现一个类似于asyn await的用法,来方便的编写callback相关函数 from __future__ import print_functionimport timeimport th ...

  8. c# 字体安装

    [DllImport("kernel32.dll", SetLastError = true)] static extern int WriteProfileString(stri ...

  9. Android——GridView(网格视图)相关知识总结贴

    Android API中文文档GridView http://www.apkbus.com/android-14131-1-1.html   Android API 中文 (15) —— GridVi ...

  10. Ay.Framework.WPF 2.0建立项目到底有多快

    2015-3-31 今天我已经优化了很多地方,让客户使用起来几乎是傻瓜式使用了,废话不多说,我们开始吧. 默认的我提供了一些图片,但是也只占用了8M多,2.0版本目前总共有45M左右大小,毕竟包含了f ...