好像园内比较多博客对 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. Redis学习笔记一:基本安装和配置

    1.安装 wget http://download.redis.io/releases/redis-3.2.3.tar.gz编译安装: tar xf redis-3.2.3.tar.gz cd red ...

  2. [Java拾遗四]JavaWeb基础之Servlet_Request&&Response

    今天来回顾下之前学过Servle的Resquest以及Response的知识.1,Request和Response技术:    rr的作用:        request是请求,封装用户的请求信息.若 ...

  3. super和this区别

    * super()和this()类似,区别是,super()从子类中调用父类的构造方法,this()在同一类内调用其它方法. 4.super和this的异同: 1)super(参数):调用基类中的某一 ...

  4. .NET中的流

    当应用程序需要和磁盘上的文件打交道的时候,就有了流的概念.流就像架设在应用程序所在内存和磁盘之间的一个管道. 大致思路 → 建立管道 //FileMode.Open打开现有文件,另外还有FileMod ...

  5. Javacript和AngularJS中的Promises

    promise是Javascript异步编程很好的解决方案.对于一个异步方法,执行一个回调函数. 比如页面调用google地图的api时就使用到了promise. function success(p ...

  6. NPOI 添加行

    IRow sourceRow = sheet1.GetRow(); ; i < dt.Rows.Count-; i++) { IRow row = sheet1.CreateRow( + i); ...

  7. js遍历jsonTree

    var json = [{tcName:"11", children:[{tcName:"22", children:[{tcName:"33&quo ...

  8. Jmeter报告优化之New XSL stylesheet

    Jmeter默认的报告展示的信息比较少,如果出错了,不是很方便定位问题.由Jmeter默认报告优化这篇文章可知,其实由.jtl格式转换为.html格式的报告过程中,style文件起了很关键的作用.下面 ...

  9. Form 表单中的Input元素回车时不保存表单

    在Form表单中如果直接在Input元素里敲回车键,那么默认将提交表单,可以通过keydown事件取消默认此操作 $("form").live('keydown',function ...

  10. python数据结构之二叉树的实现

    树的定义 树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为结点)按分支关系组织起来的结构,很象自然界中的树那样.树结构在客观世界中广泛存在,如人类社会的族谱和各种社会组织机构都可用树形 ...