对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 ...
随机推荐
- [Java拾遗三]JavaWeb基础之Servlet
Servlet 1,servlet介绍 servlet是一项动态web资源开发技术. 运行在服务器端. 作用:处理业务逻辑,生成动态的内容,返回给浏览器 ...
- atitit.GMT UTC Catitit.GMT UTC CST DST CET 星期 月份 节日 时间的不同本质and起源
atitit.GMT UTC Catitit.GMT UTC CST DST CET 星期 月份 节日 时间的不同本质and起源 1. GMT(Greenwich Mean Time)是格林尼治平时 ...
- asp提取声母源码
<% '****************************** '函数:getpychar(char) '参数:char,任意中文字符或句子 '作者:阿里西西 '日期:2007/7/15 ...
- Leetcode 299 Bulls and Cows 字符串处理 统计
A就是统计猜对的同位同字符的个数 B就是统计统计猜对的不同位同字符的个数 非常简单的题 class Solution { public: string getHint(string secret, s ...
- dom4j 读取xml
package core.util; import java.io.File; import java.util.Iterator; import java.util.List; import org ...
- MySQL Cluster 7.3.3 官方版本下载
MySQL Cluster 是 MySQL 适合于分布式计算环境的高实用.高冗余版本.它采用了NDB Cluster 存储引擎,允许在1个 Cluster 中运行多个MySQL服务器.在MyQL 5. ...
- Windows server 2008 R2充当路由器实现网络的互联(转)
1.路由器的工作原理 当IP子网中的一台主机发送IP分组给同一IP子网的另一台主机时,它将直接把IP分组送到网络上,对方就能收到.而要送给不同IP子网上的主机时,它要 选择一个能到达目的子网上的路由器 ...
- 高级屏幕空间反射: Screen Space Reflection (SSR)
自从CE3首倡SSR以来,发展至今,其质量与当年早已不能同日而语.不仅强调超越性的质量,而且强调超越性的性能.乘着周末有空撸了撸,以下是增强型实时SSR结果图.与我原来的SSR原始实现相比,新的增强型 ...
- Halcon相机标定
摄像机标定程序: 注意:E:/calibration_image :为标定图像文件路径 'E:/calibration_description/caltab_123mm.descr:为标定 ...
- 解决部份机型toast不显示问题
问题:部份机型不显示toast 解决方案: 1.自己在设置里面去允许通知,但是显然客户会说别的app都可以,so 2.自定义解决.查看toast的源码发现其附着在window上 源码下载地址:http ...