原文:改善C#程序的建议1:非用ICloneable不可的理由

好吧,我承认,这是一个反标题,实际的情况是:我找不到一个非用ICloneable不可的理由。事实上,接口ICloneable还会带来误解,因为它只有一个Clone方法。

我们都知道,对象的拷贝分为:浅拷贝和深拷贝。ICloneable仅有一个Clone方法使我们无法从命名的角度去区分到底是哪个拷贝。

浅拷贝:将对象的字段复制到副本(新的对象)中,同时将字段的值也赋值过去,但是引用类型字段只复制引用,而不是引用类型本身。这意味着,源对象引用类型字段的值改变了,会影响到副本中对应的值也改变;

深拷贝:将对象的字段复制到副本(新的对象)中,无论是值类型还是引用类型字段,都会复制类型本身及类型的值。这意味着,源对象引用类型字段的值改变了,不会影响到副本中对应的值;

于是问题来了,如果类型继承了ICloneable接口,那么类型中的Clone是浅拷贝还是深拷贝。微软的解释是:你既可以在Clone方法中实现浅拷贝,也可以实现深拷贝。那么,为什么不直接提供两个方法呢?比如:DeepClone或者ShallowClone。还是,一般类型的创建,只要实现了浅拷贝就不需要再实现深拷贝(或者反之),所以我们没有必要提供两个方法。

下面是一个既实现了浅拷贝也实现深拷贝的例子:

代码

, SeekOrigin.Begin);
return formatter.Deserialize(objectStream) as Employee;
}
}

public Employee ShallowClone()
{
return Clone() as Employee;
}
}

实际上,ICloneable还带来一个问题(该问题Bill Wagner在Effcitive c#中曾经论述过),那就是:如果类型继承自ICloneable,但是同时它不是一个Sealed类型的话,它们的子类的默认Clone方法会带来BUG(子类的Clone方法会返回父类的副本,而不是子类本身)。这会逼迫所有的子类都重写Clone方法;

ICloneable的Clone方法的另一个问题是:它不是类型安全的,它返回的是Object,使用它的时候还设计到转型的问题,而我们自己实现的Clone方法却可以规避掉这个问题(如上文代码)。

综上所述,类型确实没必要继承ICloneable接口,如果类型本身需要实现拷贝功能,直接公开方法就行。如果在应用中你觉得确实必须实现这个接口的,来指正我吧。

微信扫一扫,关注最课程(www.zuikc.com),获取更多我的文章,获取软件开发每日一练

改善C#程序的建议1:非用ICloneable不可的理由的更多相关文章

  1. [No0000178]改善C#程序的建议1:非用ICloneable不可的理由

    好吧,我承认,这是一个反标题,实际的情况是:我找不到一个非用ICloneable不可的理由.事实上,接口ICloneable还会带来误解,因为它只有一个Clone方法. 我们都知道,对象的拷贝分为:浅 ...

  2. [转]改善C#程序的建议4:C#中标准Dispose模式的实现

    需要明确一下C#程序(或者说.NET)中的资源.简单的说来,C#中的每一个类型都代表一种资源,而资源又分为两类: 托管资源:由CLR管理分配和释放的资源,即由CLR里new出来的对象: 非托管资源:不 ...

  3. 改善C#程序的建议10:用Parallel简化Task

    在命名空间System.Threading.Tasks下,有一个静态类Parallel简化了在同步状态下的Task的操作.Parallel主要提供了3个有用的方法:For.ForEach.Invoke ...

  4. 改善C#程序的建议8:避免锁定不恰当的同步对象

    原文:改善C#程序的建议8:避免锁定不恰当的同步对象 在C#中让线程同步的另一种编码方式就是使用线程锁.所谓线程锁,就是锁住一个资源,使得应用程序只能在此刻有一个线程访问该资源.可以用下面这句不是那么 ...

  5. 改善C#程序的建议6:在线程同步中使用信号量

    原文:改善C#程序的建议6:在线程同步中使用信号量 所谓线程同步,就是多个线程之间在某个对象上执行等待(也可理解为锁定该对象),直到该对象被解除锁定.C#中对象的类型分为引用类型和值类型.CLR在这两 ...

  6. 改善C#程序的建议7:正确停止线程

    原文:改善C#程序的建议7:正确停止线程 开发者总尝试对自己的代码有更多的控制.“让那个还在工作的线程马上停止下来”就是诸多要求中的一种.然而事与愿违,这里面至少存在两个问题: 第一个问题是:正如线程 ...

  7. 编写高质量代码--改善python程序的建议(六)

    原文发表在我的博客主页,转载请注明出处! 建议二十八:区别对待可变对象和不可变对象 python中一切皆对象,每一个对象都有一个唯一的标识符(id()).类型(type())以及值,对象根据其值能否修 ...

  8. 编写高质量代码–改善python程序的建议(五)

    原文发表在我的博客主页,转载请注明出处! 建议二十三:遵循异常处理的几点基本原则 python中常用的异常处理语法是try.except.else.finally,它们可以有多种组合,语法形式如下: ...

  9. 编写高质量代码--改善python程序的建议(八)

    原文发表在我的博客主页,转载请注明出处! 建议四十一:一般情况下使用ElementTree解析XML python中解析XML文件最广为人知的两个模块是xml.dom.minidom和xml.sax, ...

随机推荐

  1. IT增值服务实践心得体会:企业客户的钱比个人客户好赚得多

    友情提示 本人喜欢直言不讳,不喜欢拐弯抹角.喜欢从客观和主观.自身和他人等多种角度去探讨问题.如有不当之处,欢迎吐槽. 若干心得体会1.企业客户的钱更好赚,个人客户的钱很难.  为什么这么说呢? a. ...

  2. iPhone6/6Plus下app状态栏内容放大问题处理

    分为兼容模式和高分辨率模式. 兼容模式 当你的 app 没有提供 3x 的 LaunchImage 时,系统默认进入兼容模式,大屏幕一切按照 320 宽度渲染,屏幕宽度返回 320:然后等比例拉伸到大 ...

  3. 【CTO俱乐部研修班开课】看板先驱David J. Anderson:看板核心在于创造一种能力——提升敏捷性

    看板开发方法是近年来最热门的敏捷和精益开发方法.看板之父David J. Anderson觉得其核心在于帮助企业创造一种能力--提升敏捷性.CTO俱乐部看板研修班将通过理论.沙盘模拟.真实案例分享等阐 ...

  4. Swift学习——Swift解释具体的基础(六)

    Optionals    可选 可选(它似乎并不如此翻译)它适用于那些值这种情况可能是空的,有两种情况一个可选:存在值并等于x,要么值不存在. 选配的概念在OC和C里面并没有.在OC中最接近的概念就是 ...

  5. 80. Domino Internet Password

    Internet口令保存在Domino文件夹的个人文档的HTTPPassword域中,和文档中的username一起用于藉各种Internet协议訪问Dominoserver时的校验,最经常使用的就是 ...

  6. Cordova app 检查更新 ----JS进行调用(二)

    原文:Cordova app 检查更新 ----JS进行调用(二) 1.获取版本号 需要添加 插件 cordova plugin add https://github.com/whiteoctober ...

  7. Android中间httpclient发送帧get求

    /** * 採用httpclientGet请求的方式 * * @param username * @param password * @return null表示求得的路径有问题,text返回请求得到 ...

  8. C#中的interface没那么简单

    最近在园子里闲逛看到一篇文章“(抽象)类和接口细节分析”,尽管作者很细心很细致.可事实上C#里面的interface没那么简单,interface有着大量不为人知的小秘密的说. 1.值类型也能实现接口 ...

  9. 矩阵微分(matrix derivatives)

    关于矩阵求导,得到的导数则是矩阵形式:关于矢量求导,得到的导数则是矢量形式:关于标量求导,得到的仍是标量形式.也即关于谁求导,得到的导数形式便和谁的维度信息一致. fx = f(x) grad = n ...

  10. HDU 4862 Jump(更多的联合培训学校1)(最小费用最大流)

    职务地址:pid=4862">HDU4862 最小费用流做的还是太少. 建图想不出来. . . 直接引用官方题解的话吧... 最小K路径覆盖的模型.用费用流或者KM算法解决,构造二部图 ...