首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

Effective C# 原則 27:避免實作 ICloneable,簡化複製語意與繼承負擔

     編輯:關於C#

ICloneable 的模糊契約

ICloneable 定義單一方法 Clone(),但文件同時支援淺層複製與深層複製,未強制規範。這導致:

  • 消費者無法得知複製深度。
  • 衍生類別被迫一致實作,負擔沈重。
  • 含循環參考的物件圖複製極其複雜。

實值型別:完全不需 ICloneable

  • 純實值型別成員:單純指派即為高效複製,無需裝箱/拆箱開銷。
  • 含參考型別成員(如 string):string 為不可變型別,淺層複製安全。其他參考型別若需深層複製,手動實作更清晰。

結論:沒有任何理由給實值型別實作 ICloneable。

參考型別:繼承鏈上的複製噩夢

class BaseType : ICloneable {
    public object Clone() {
        var r = new BaseType(); // 僅複製基類部分!
        r._label = _label;
        Array.Copy(_values, r._values, _values.Length);
        return r;
    }
}
class Derived : BaseType { ... }
// Derived.Clone() 回傳 BaseType 實例,轉型失敗得 null

基類實作 ICloneable 強制所有衍生類別必須正確覆寫,否則行為錯誤。這對衍生類別是嚴苛契約。

改良模式:受保護複製建構函式 + 葉類實作

  1. 基類不實作 ICloneable,提供 protected BaseType(BaseType other) 複製建構函式。
  2. 衍生類別若需複製,自行實作 ICloneable 並呼叫基類複製建構函式。
  3. 葉類別(sealed)實作 ICloneable,終結繼承鏈複製義務。
class BaseType {
    protected BaseType(BaseType other) { ... } // 複製基類欄位
}
sealed class Derived : BaseType, ICloneable {
    private Derived(Derived other) : base(other) { ... }
    public object Clone() => new Derived(this);
}

總結

  • 實值型別:使用指派複製,勿實作 ICloneable。
  • 參考型別:僅在葉類別必要時實作 ICloneable。
  • 基類:提供受保護複製建構函式協助衍生類別,不強制實作介面。

盡量避免 ICloneable,讓類別設計更簡單、更安全。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved