Effective C#:避免使用ICloneable接口
? ? ? 最近在學習Bill Wagner的書籍:《Effective C#:50 Specific Ways to Improve Your C#》,雖然是一本很早的書了,但是感覺很實用,并且跟國內出版的許多“提高代碼質量的XXX條建議"之類的書籍相比,其實大部分的解釋都大同小異,所以準備以此為基礎,決定對學習過程中的理解做一些記錄。
? ? ? ICloneable接口,在MSDN上的解釋很簡單:支持克隆,即創建一個與原實例擁有相同成員值的新實例副本。ICloneable接口只有一個成員方法,Clone()。一切看起來沒有什么復雜的,但是使用過該接口之后,你就會發現潛藏的問題不少。
? ? ? 既然是對對象的拷貝功能,那就涉及到了深拷貝和淺拷貝的問題。
? ? ? 淺拷貝:將對象中的所有字段復制到新的對象(副本)中。其中,值類型字段的值被復制到副本中后,在副本中的修改不會影響到源對象對應的值。而引用類型的字段被復制到副本中的是引用類型的引用,而不是引用的對象,在副本中對引用類型的字段值做修改會影響到源對象本身。
? ? ? 深拷貝:將對象中的所有字段復制到新的對象中。不過,無論是對象的值類型字段,還是引用類型字段,都會被重新創建并賦值,對于副本的修改,不會影響到源對象本身。
? ? ? 由于只有一個Clone方法,那么調用者在調用第三方提供的Clone方法的時候,也就不能確認自己得到的拷貝對象,到底是深拷貝還是淺拷貝。MSDN上也提到:Clone方法不能明確告知返回的對象到底是深拷貝,淺拷貝,還是介于二者之間的拷貝。許多專家也對這種現象予以指責。同時,本人在使用ICloneable的時候,想到,既然只是拷貝的問題,那么提供淺拷貝和深拷貝兩個公共方法就行了,為什么還要用Cloneable呢?有解釋是微軟建議用類型繼承ICloneable接口的方式明確告訴調用者:該類型可以被拷貝。不知道還有沒有其它的解釋呢。
? ? ? 使用ICloneable的第二個問題,就是如果基類繼承了ICloneable接口,并且非Sealed類型,那么它的所有派生類都需要實現Clone方法。否則,用派生類對象調用Clone方法,返回的對象將會是基類Clone方法創建的對象,這就給派生類帶來了沉重的負擔。所以應盡量避免在非密封類中實現ICloneable。
? ? ? 第三個需要注意的問題,就是Clone方法必須對返回值裝箱,讓其變成一個System.Object引用,也就是說Clone方法返回值是非類型安全的。不僅如此,隨后,調用者還需要拆箱,進行對象轉型操作。
? ? ? 第四個問題,就是由于ICloneable使用的結果經常是弊大于利,所以.Net Framework在升級支持泛型時沒有添加ICloneable<T>。
? ? ? 根據ICloneable使用上的問題,Bill Wagner建議:對于值類型,永遠都不要實現ICloneable,直接使用賦值操作即可。對于那些葉子類,僅在真正需要復制操作時再添加ICloneable支持。對于那些派生類很有可能會支持ICloneable的基類來說,你可以創建一個受保護的復制結構函數,供派生類使用。在其他的各種情況下,應盡量避免使用ICloneable。
? ? ??
參考資料:Bill Wagner,《Effective C#:50 Specific Ways to Improve Your C#》
? ? ? ? ? ? ? 陸敏技 博客:http://www.cnblogs.com/luminji/archive/2011/02/02/1948826.html
? ? ? ? ? ? ? MSDN blogs:http://blogs.msdn.com/b/mrtechnocal/archive/2009/10/19/why-not-icloneable-t.aspx
轉載于:https://www.cnblogs.com/ByronsHome/p/3366596.html
總結
以上是生活随笔為你收集整理的Effective C#:避免使用ICloneable接口的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 二年级上册妈妈睡了生字组词
- 下一篇: 我的人生我做主的短句励志的 命运由自己掌