博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
改善C#程序的建议1:非用ICloneable不可的理由
阅读量:4935 次
发布时间:2019-06-11

本文共 1605 字,大约阅读时间需要 5 分钟。

原文:

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

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

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

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

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

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

代码
[Serializable]
class
Employee : ICloneable
{
public
string
IDCode {
get
;
set
; }
public
int
Age {
get
;
set
; }
public
Department Department {
get
;
set
; }
#region
ICloneable 成员
public
object
Clone()
{
return
this
.MemberwiseClone();
}
#endregion
public
Employee DeepClone()
{
using
(Stream objectStream
=
new
MemoryStream())
{
IFormatter formatter
=
new
BinaryFormatter();
formatter.Serialize(objectStream,
this
);
objectStream.Seek(
0
, 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接口,如果类型本身需要实现拷贝功能,直接公开方法就行。如果在应用中你觉得确实必须实现这个接口的,来指正我吧。

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

 

posted on
2017-09-25 08:36 阅读(
...) 评论(
...)

转载于:https://www.cnblogs.com/lonelyxmas/p/7590272.html

你可能感兴趣的文章
使用wxWidgets for C++从资源文件中静态装载图像
查看>>
提高数据库安全性的办法
查看>>
工作流编程循序渐进(8:状态机工作流)
查看>>
3.VMware View 4.6安装与部署-connection server(View Standard Server)
查看>>
Lync Server 2013 实战系列之六:标准版-安装和更新LyncServer 系统
查看>>
MariaDB日志审计 帮你揪出内个干坏事儿的小子
查看>>
Reporting Services目录临时数据库文件存在
查看>>
一个Windows Mobile, Windows Embedded CE工程师的找工经历(一)
查看>>
终于有了MSDN上的Blog
查看>>
PHPUnit学习03---使用Mock对象解决测试依赖
查看>>
java类型与Hadoop类型之间的转换
查看>>
允许SQL Server 2005远程连接
查看>>
微软为asp.net ajax和jquery创建了CDN
查看>>
Chris:怎样成为一名Android应用开发
查看>>
常见的makefile写法【转】
查看>>
和菜鸟一起学linux总线驱动之初识spi驱动数据传输流程【转】
查看>>
WorkFlow设计篇Step.4—异常处理(续)-WF4.0
查看>>
GNU make manual 翻译( 一百零三)
查看>>
深入浅出 React Native:使用 JavaScript 构建原生应用
查看>>
RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2-> Web版本新增新的用户权限设置界面效率更高、更规范...
查看>>