首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C# 多類共同字段設計:繼承 vs 組合 vs 接口的抉擇指南

     編輯:程式設計疑難解答

問題核心

多個類擁有相同字段(如 Id、CreateTime、IsDeleted),如何設計既避免重複代碼,又保持靈活擴展?

方案對比矩陣

方案適用場景優點缺點代碼示例
基類繼承強「是一種」關係,共享行為代碼復用最簡單,多態天然支持單繼承限制,耦合度高,脆弱基類問題class EntityBase { int Id; } class User : EntityBase {}
組合/聚合共享數據結構,無行為耦合靈活、可運行時替換、符合「組合優於繼承」需轉發調用,略顯繁瑣class AuditInfo { DateTime Created; } class Order { AuditInfo Audit; }
接口 + 默認實現定義契約,C# 8.0+ 支持默認方法多實現、無狀態、可混入無法定義實例字段(僅屬性),邏輯受限interface IAuditable { DateTime Created {get;} }
擴展方法為現有類型添加共用邏輯不侵入原類型,語法糖友好無法存儲狀態,僅行為復用static class EntityExt { public static bool IsNew(this IEntity e) => e.Id == 0; }

推薦決策流程

  1. 是否為核心領域實體? → 是 → 基類 EntityBase(含 Id、版本號、軟刪除)。
  2. 是否為橫切關注點(审計、軟刪除、租戶)? → 組合模式:AuditInfo、TenantInfo 作為值對象嵌入。
  3. 需要多實現/插件化? → 接口 IAuditable + 擴展方法提供默認行為。
  4. 僅需工具方法? → 擴展方法或靜態工具類。

最佳實踐代碼範例

// 1. 基礎實體(繼承)
public abstract class EntityBase {
    public int Id { get; protected set; }
    public DateTime CreatedAt { get; protected set; } = DateTime.UtcNow;
    public bool IsDeleted { get; protected set; }
}

// 2. 審計信息(組合 - 值對象)
public record AuditInfo(DateTime CreatedAt, string CreatedBy, DateTime? UpdatedAt, string UpdatedBy);

// 3. 實體使用組合
public class Order : EntityBase {
    public string OrderNo { get; set; }
    public AuditInfo Audit { get; private set; }
    public void MarkCreated(string user) => Audit = new AuditInfo(DateTime.UtcNow, user, null, null);
}

// 4. 接口契約(可選)
public interface ISoftDeletable {
    bool IsDeleted { get; }
    void Delete();
}
public static class SoftDeleteExtensions {
    public static void SafeDelete(this ISoftDeletable e) {
        if (!e.IsDeleted) e.Delete();
    }
}

避坑指南

  • ❌ 將所有共同字段塞進一個巨大的 BaseEntity → 導致「上帝基類」。
  • ❌ 強行讓無關類繼承同一基類只為復用字段 → 違反里氏替換原則。
  • ✅ 按業務語義劃分:標識符歸基類,審計歸值對象,行為歸接口/擴展方法。

「共同字段」不等於「共同繼承」 —— 用組合拆解橫切關注點,用接口定義契約,讓類層次清晰、可測試、可演化。

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