【问题标题】:Should one use self-referencing generic inheritance like Customer : Entity<Customer>是否应该使用自引用的通用继承,例如 Customer : Entity<Customer>
【发布时间】:2011-01-11 19:58:56
【问题描述】:

是否建议使用自引用泛型继承?

public abstract class Entity<T> {
    public Guid Id {get; set;}
    public int Version {get; set;}

    public T Clone() {
        ...
        // clone routine
        ...
        return T;
    }
}

public class Customer : Entity<Customer> {
    public string CustomerName {get; set;}
    ...
}

如何将 Customer 转换为基 Entity 类? “客户:实体”提供什么优势?我在展示 NHibernate 域建模的示例中看到了这种继承。

在没有泛型的情况下使用“客户:实体”会更好吗?

【问题讨论】:

    标签: c# nhibernate generics inheritance


    【解决方案1】:

    您应该在需要时使用它,而不仅仅是因为可以。在上面的例子中,实现Clone() 是有意义的。但是,正如您正确指出的那样,这意味着您的实体类实际上没有公共基类,并且它们真正共有的属性将无法访问。处理此问题的正确方法是将其拆分为通用和非通用部分:

    public abstract class Entity {
        public Guid Id {get; set;}
        public int Version {get; set;}
    }
    
    public abstract class Entity<T> : Entity where T : Entity<T> {
        public T Clone() {
            ...
            // clone routine
            ...
            return T;
        }
    }
    

    另外,请注意我添加到 Entity&lt;T&gt; 声明中的 where 部分 - 它确保此类只能用作此递归模式的一部分。

    【讨论】:

    • 使用通用实体还有其他好处吗?如果没有其他优势,我可以将 Clone 方法设为通用方法。
    • 你如何使Clone 通用?
    • 我可以做 public T Clone() { 序列化/反序列化 T,返回 T}
    • 但是这意味着如果你有实体类FooBar,你可以调用bar.Clone&lt;Foo&gt;()。那应该怎么做?
    • 也许我可以在实体上创建一个静态克隆类。我的问题是,除了克隆示例之外,自引用是否还有其他优势。
    【解决方案2】:

    在我工作的公司中,我从事的项目大量使用这种技巧。事实上,它甚至被提升为代码中的一种模式。因此我可以根据经验说话:不要使用它。

    它们可能是自引用实现更简单、更高效且更易于阅读的情况,但我从未遇到过这样的情况。大量使用它会使代码维护成为一场噩梦,在大多数情况下,只需正常继承和在需要时转换方法结果即可避免。与代码的维护成本相比,转换为派生类的性能成本可以忽略不计。

    因此,如果您发现建议使用自引用泛型继承的罕见示例,请继续这样做。但请事先三思,因为可能有更好的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-26
      • 1970-01-01
      • 1970-01-01
      • 2013-09-26
      相关资源
      最近更新 更多