改善C#程序的建议1:非用ICloneable不可的理由
来源:互联网 发布:阿里云邮箱故障 编辑:程序博客网 时间:2024/05/17 23:16
作者:Luminji
转自:http://www.cnblogs.com/luminji/archive/2011/02/02/1948826.html
好吧,我承认,这是一个反标题,实际的情况是:我找不到一个非用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接口,如果类型本身需要实现拷贝功能,直接公开方法就行。如果在应用中你觉得确实必须实现这个接口的,来指正我吧。
- 改善C#程序的建议1:非用ICloneable不可的理由
- 改善C#程序的建议1:非用ICloneable不可的理由
- 改善C#程序的建议1:非用ICloneable不可的理由
- 改善C#程序的建议2:非用ICloneable不可的理由
- 改善C#程序的若干建议
- 改善C#程序的建议10:用Parallel简化Task
- 改善C#程序的建议1:正确停止线程
- 改善C#程序的157个建议--读书笔记
- 改善C#程序的建议7:正确停止线程
- 改善C#程序的建议7:正确停止线程
- 改善Java文档的理由、建议和技巧
- 改善Java文档的理由、建议和技巧
- 改善Java文档的理由、建议和技巧
- 改善Java文档的理由、建议和技巧
- 改善c#程序建议集1
- 《编写高质量代码 : 改善C#程序的157个建议》读书笔记 1-10
- 改善C#编程的50个建议(1-5)
- 读改善java程序的151个建议(1)
- JavaScript对象编程- 创建类/对象的几种方式
- vs2010向解决方案中添加已有工程
- 2014年十大热门技术看点
- 不让系统进休眠(调试时有时会用到)
- 关于协方差矩阵的理解
- 改善C#程序的建议1:非用ICloneable不可的理由
- getchar 和 getch 详解
- Linq查询出现"此上下文仅支持基元类型或枚举类型。"解决方法
- 手机网站页面制作更应该符合WEB标准
- 好帖子收集总结
- POJ2661 Factstone Benchmark
- 转载一个C#应用程序打包的详细教程,超详细!
- UNDO 100%
- git rebase 小计