改善C#程序的建议1:非用ICloneable不可的理由
原文:改善C#程序的建议1:非用ICloneable不可的理由
好吧,我承认,这是一个反标题,实际的情况是:我找不到一个非用ICloneable不可的理由。事实上,接口ICloneable还会带来误解,因为它只有一个Clone方法。
我们都知道,对象的拷贝分为:浅拷贝和深拷贝。ICloneable仅有一个Clone方法使我们无法从命名的角度去区分到底是哪个拷贝。
浅拷贝:将对象的字段复制到副本(新的对象)中,同时将字段的值也赋值过去,但是引用类型字段只复制引用,而不是引用类型本身。这意味着,源对象引用类型字段的值改变了,会影响到副本中对应的值也改变;
深拷贝:将对象的字段复制到副本(新的对象)中,无论是值类型还是引用类型字段,都会复制类型本身及类型的值。这意味着,源对象引用类型字段的值改变了,不会影响到副本中对应的值;
于是问题来了,如果类型继承了ICloneable接口,那么类型中的Clone是浅拷贝还是深拷贝。微软的解释是:你既可以在Clone方法中实现浅拷贝,也可以实现深拷贝。那么,为什么不直接提供两个方法呢?比如:DeepClone或者ShallowClone。还是,一般类型的创建,只要实现了浅拷贝就不需要再实现深拷贝(或者反之),所以我们没有必要提供两个方法。
下面是一个既实现了浅拷贝也实现深拷贝的例子:
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不可的理由的更多相关文章
- [No0000178]改善C#程序的建议1:非用ICloneable不可的理由
好吧,我承认,这是一个反标题,实际的情况是:我找不到一个非用ICloneable不可的理由.事实上,接口ICloneable还会带来误解,因为它只有一个Clone方法. 我们都知道,对象的拷贝分为:浅 ...
- [转]改善C#程序的建议4:C#中标准Dispose模式的实现
需要明确一下C#程序(或者说.NET)中的资源.简单的说来,C#中的每一个类型都代表一种资源,而资源又分为两类: 托管资源:由CLR管理分配和释放的资源,即由CLR里new出来的对象: 非托管资源:不 ...
- 改善C#程序的建议10:用Parallel简化Task
在命名空间System.Threading.Tasks下,有一个静态类Parallel简化了在同步状态下的Task的操作.Parallel主要提供了3个有用的方法:For.ForEach.Invoke ...
- 改善C#程序的建议8:避免锁定不恰当的同步对象
原文:改善C#程序的建议8:避免锁定不恰当的同步对象 在C#中让线程同步的另一种编码方式就是使用线程锁.所谓线程锁,就是锁住一个资源,使得应用程序只能在此刻有一个线程访问该资源.可以用下面这句不是那么 ...
- 改善C#程序的建议6:在线程同步中使用信号量
原文:改善C#程序的建议6:在线程同步中使用信号量 所谓线程同步,就是多个线程之间在某个对象上执行等待(也可理解为锁定该对象),直到该对象被解除锁定.C#中对象的类型分为引用类型和值类型.CLR在这两 ...
- 改善C#程序的建议7:正确停止线程
原文:改善C#程序的建议7:正确停止线程 开发者总尝试对自己的代码有更多的控制.“让那个还在工作的线程马上停止下来”就是诸多要求中的一种.然而事与愿违,这里面至少存在两个问题: 第一个问题是:正如线程 ...
- 编写高质量代码--改善python程序的建议(六)
原文发表在我的博客主页,转载请注明出处! 建议二十八:区别对待可变对象和不可变对象 python中一切皆对象,每一个对象都有一个唯一的标识符(id()).类型(type())以及值,对象根据其值能否修 ...
- 编写高质量代码–改善python程序的建议(五)
原文发表在我的博客主页,转载请注明出处! 建议二十三:遵循异常处理的几点基本原则 python中常用的异常处理语法是try.except.else.finally,它们可以有多种组合,语法形式如下: ...
- 编写高质量代码--改善python程序的建议(八)
原文发表在我的博客主页,转载请注明出处! 建议四十一:一般情况下使用ElementTree解析XML python中解析XML文件最广为人知的两个模块是xml.dom.minidom和xml.sax, ...
随机推荐
- [React] displayName for stateless component
We can use 'displayName' on component to change its component tag in dev tool: import React from 're ...
- ts demuxer的加入记录
文件夹 1 初衷 2 ts demux的功能介绍 1 初衷 之前打算给dtplayer加入一些亮点功能,最初的想法是:bt下载播放 + hls支持 bt下载因为以来libtorrent库,尽管搞懂了怎 ...
- UIPasteboard粘贴板:UIlabel开启复制粘贴功能(一)
首先,因为苹果只放出来了 UITextView,UITextField,webView三个控件的剪贴板,所以一般控件的剪贴板都被禁用了,因此,我们首先要做的就是把这属性放出来,其实就是实现三个简单的方 ...
- ZooKeeper 分布式锁实现原理
原理 进程需要访问共享数据时, 就在"/locks"节点下创建一个sequence类型的子节点, 称为thisPath. 当thisPath在所有子节点中最小时, 说明该进程获得了 ...
- 【codeforces 777D】Cloud of Hashtags
[题目链接]:http://codeforces.com/contest/777/problem/D [题意] 让你通过删除字符串的末尾字符的方式; 使得所给的字符串以字典序升序排序; 不能交换字符串 ...
- 属性动画Property Animation
ViewPropertyAnimation 使用方式:View.animate() 后跟 translationX() 等方法,动画会自动执行. 注意translationX实现是调用对应的set方法 ...
- selenium 爬取空间说说
package cn.hb.util; import java.io.File; import java.io.FileWriter; import java.io.IOException; impo ...
- How to provide highlighting with Spring data elasticsearch
How to provide highlighting with Spring data elasticsearch @Test public void shouldReturnHighlighted ...
- 将普通java工程转换成maven工程
在MyEclipse10中将Maven项目转成普通Java项目后,想将Java项目转成Maven项目,结果一下子傻眼了.根本就没有攻略中提到的config标签.仔细一看,喵咪的,人家用的是Eclips ...
- R 语言的学习(一)
1. 基本 "hello world!" > "hello world!" [1] "hello world!" 这在 R 中并不是一 ...