对C#对象的Shallow、Deep Cloning认识【转】
好像园内比较多博客对 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认识【转】的更多相关文章
- GC之二--GC是如何回收时的判断依据、shallow(浅) size、retained(保留) size、Deep(深)size
回到问题“为何会内存溢出?”. 要回答这个问题又要引出另外一个话题,既什么样的对象GC才会回收? 一.对象存活方式判断方法 在上一篇文章<GC之一--GC 的算法分析.垃圾收集器.内存分配策略介 ...
- Java:浅克隆(shallow clone)与深克隆(deep clone)
Summary 浅克隆与深克隆对于JavaSE来说,是个难度系数比较低的概念,但不应该轻视它. 假设一个场景:对于某个list,代码里并没有任何对其的直接操作,但里面的元素的属性却被改变了,这可能就涉 ...
- 《Beginning Java 7》 - 2 - Cloning 克隆
Cloning 分两类:影子克隆 shallow cloning 深度克隆 deep cloning * 调用 clone() 需要 implments Cloneable.此函数为 protecte ...
- 《JavaScript 模式》读书笔记(5)— 对象创建模式2
这一篇,我们主要来学习一下私有属性和方法以及模块模式. 三.私有属性和方法 JavaScript并没有特殊的语法来表示私有.保护.或公共属性和方法,在这一点上与Java或其他语言是不同的.JavaSc ...
- [Java基础] Java对象内存结构
转载地址:http://www.importnew.com/1305.html 原文于2008年11月13日 发表, 2008年12月18日更新:这里还有一篇关于Java的Sizeof运算符的实用库的 ...
- net对象的克隆
class Person { public string name; public List<string> hobby; } void main() { Person p1 = new ...
- JAVA Shallow heap & Retained heap
最近在研究内存泄漏的问题,在使用MAT工具中发现了Shallow heap & Retained heap,不懂. 然后在网上找了一些资料. Shallow Size 对象自身占用的内存大小, ...
- Shallow Size 和 Retained Size
所有包含Heap Profling功能的工具(MAT, Yourkit, JProfiler, TPTP等)都会使用到两个名词,一个是Shallow Size,另一个是 Retained Size. ...
- Java高效编程之二【对所有对象都通用的方法】
对于所有对象都通用的方法,即Object类的所有非final方法(equals.hashCode.toString.clone和finalize)都有明确的通用约定,都是为了要被改写(override ...
随机推荐
- C#与数据库访问技术总结(六)之Command对象创建SQl语句代码示例
Command对象创建SQl语句代码示例 说明:前面介绍了 Command 对象的方法和一些属性,回顾一下 Command对象主要用来执行SQL语句.利用Command对象,可以查询数据和修改数据. ...
- servlet web文件上传
web文件上传也是一种POST方式,特别之处在于,需设置FORM的enctype属性为multipart/form-data. 并且需要使用文件域. servlet的代码比较关键是这几句: // 使用 ...
- JProfiler使用详细教程学习笔记
JProfiler学习笔记 推荐文章:JProfiler 入门教程 一.安装JProfiler 从http://www.ej-technologies.com/下载5.1.2并申请 ...
- [Python爬虫] Selenium自动访问Firefox和Chrome并实现搜索截图
前两篇文章介绍了安装,此篇文章算是一个简单的进阶应用吧!它是在Windows下通过Selenium+Python实现自动访问Firefox和Chrome并实现搜索截图的功能. [Pyth ...
- 公钥,私钥,SSL(讲的很生动) (转) 对称加密、非对称加密初探
最近开始做消息推送,有不少概念性的东西需要知道,首先应该了解的是密钥.这片文章很清晰的讲解了对称密钥.非对称密钥.ssl的知识. 原文地址:http://chenling1018.blog.163.c ...
- IOS设计模式的六大设计原则之开放-关闭原则(OCP,Open-Close Principle)
定义 一个软件实体(如类.模块.函数)应当对扩展开放,对修改关闭. 定义解读 在项目开发的时候,都不能指望需求是确定不变化的,大部分情况下,需求是变化的.那么如何应对需求变化的情况?这就是开放-关闭原 ...
- iOS数据持久化-OC
沙盒详解 1.IOS沙盒机制 IOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都要保存在此,例如图像,图标,声音,映像,属性列表,文 ...
- 如何安装、配置Apache
Apache的安装流程网上版本很多,但很多版本有错误,或者缺漏,如果初学者按照那样安装的话会遇到各种各样的问题.我整理了自己安装.配置Apache的过程,亲测有效,分享给大家. 基本过程如下: Dow ...
- Javascript基础恶补
1.字符集:Javascript采用Unicode字符集,支持地球上所有在用的语言. 2.区分大小写:Javascript区分大小写,HTML不区分大小写. 3.空格.换行.格式控制符:Javascr ...
- EWM 强大的数据修复功能
在上了EWM系统后,运行一段时间可能因为不正确的操作,系统意外情况数据不一致的问题,交货单行项目状态不致,等等报不一致的情况,EWM的自检功能比较强. 下面介绍一种数据不致的修复工具之一,tx: /S ...