代码之家  ›  专栏  ›  技术社区  ›  Michal Ciechan

C#泛型继承

  •  3
  • Michal Ciechan  · 技术社区  · 14 年前

    public class AccountingBase<TItemType> where TItemType : AccountingItemBase
    

    在我的AccountingItemBase中,我有以下属性:

    public virtual AccountingBase<AccountingItemBase> Parent { get; set; }
    

    在我的会计基础中,我试图做以下工作

    item.Parent = this;
    

    从逻辑上讲,这应该是可行的,因为TItemType继承自AccountingItemBase,但是我得到了以下错误:

    > Error 1 Cannot implicitly convert type
    > 'TGS.MySQL.DataBaseObjects.AccountingBase<TItemType>'
    > to
    > 'TGS.MySQL.DataBaseObjects.AccountingBase<TGS.MySQL.DataBaseObjects.AccountingItemBase>'
    

    如何将子属性parent属性设置为自身(在父类内部)

    2 回复  |  直到 14 年前
        1
  •  6
  •   Jon Skeet    14 年前

    不,你的直觉是错误的。它不应该工作,因为泛型类在.NET中不是变体。

    只是因为 TItemType AccountingItemBase 并不意味着 AccountingBase<TItemType> AccountingBase<AccountingItemBase> . 假设 会计基础<TItemType> 滴度类型 . 如果你的直觉是正确的,你可以写:

    AccountingBase<SomeSubtype> x = new AccountingBase<SomeSubtype>();
    AccountingBase<AccountingItemBase> y = x;
    y.SomeField = new OtherSubtype();
    

    这显然会破坏类型安全,因为 AccountingBase<SomeSubtype> ,字段的类型是 SomeSubtype ,但您已将 OtherSubtype 在里面!

    我建议你读埃里克·利珀特的长篇大论 blog post series 更多信息。或者我有个视频 NDC 2010 一些 一般变异,但有限。

    • 你可以创建一个 非通用的 AccountingBase 继承自。这可能是最好的主意。然后将 Parent 非泛型类型的属性。
    • 会计基础 它本身和它的父。。。但最终导致递归问题,实际上。。。
        2
  •  2
  •   Dan Bryant    14 年前

    除了乔恩的选择,你还可以:

    • IAccountingBase 它只提供AccountingItemBase完成其工作所需的有限访问权限(类似于非泛型基类,但进一步抽象)

    • 重新构造代码,使AccountingItemBase不需要父引用来完成其工作。我的经验是,循环依赖关系(所有者知道关于所有者的项)是设计的症状,其中子实例承担了太多的责任。有时可以通过将功能移到父级或将其移到更高级别的类(在单个父级的上下文中对多个项执行复杂操作)来解决此问题,从而消除了每个项都有父引用的需要。例如,如果您的项公开了与帐户调节相关的函数,那么您可能有一个AccountReconciler类,而不是将函数放在项上。