C# 这是一个很好地利用继承的例子吗?

C# 这是一个很好地利用继承的例子吗?,c#,inheritance,C#,Inheritance,我一直在读到继承通常是糟糕的代码设计。尽管如此,我有时还是会继承业务对象的列表或绑定列表。下面是一个我可以使用的简单业务对象: public class RowType { public string Name { get; set; } public double Sales { get; set; } } 对于包含RowTypes集合的对象,有两个选项: //Option A: "Has-A" relationship public class RowHolderType

我一直在读到继承通常是糟糕的代码设计。尽管如此,我有时还是会继承业务对象的列表或绑定列表。下面是一个我可以使用的简单业务对象:

public class RowType
{
    public string Name { get; set; }
    public double Sales { get; set; }
}
对于包含
RowType
s集合的对象,有两个选项:

//Option A: "Has-A" relationship
public class RowHolderType
{
    private readonly BindingList<RowType> _rows;
    public BindingList<RowType> Rows { get { return this._rows; } }
    public RowHolderType() { this._rows = new BindingList<RowType>(); }
}

//Option B: "Is-A" relationship
public class RowHolderType : BindingList<RowType>
{
    public RowHolderType() : base() { }
    public RowHolderType(IList<RowType> list) : base(list) { }
}

调用者负责发送
更改前列表
更改后列表
通知。我还没有尝试使用“Has-a”类型的关系,但我认为该代码会更难看。(请注意,我遗漏了
RowTypeHolderEventArgs
RowTypeHolderEventArgs.ChangeType
的定义。我认为这对于这个例子并不重要。)

没有更多的上下文,我很难决定我更喜欢哪一个,我通常喜欢根据我的问题心理模型来构造代码

问问自己这个问题:


是修辞意义上的
行持有者类型
绑定列表
?如果是,则表示继承是100%合适的

我一直在读到继承通常是糟糕的代码设计。
哪里?这是胡说八道。选择B通常是你最好的选择。如果你的设计中有什么不好的地方,那就是调用你的类
RowType
,它并没有告诉我它到底是什么。这要看情况而定。为什么要首先创建这样一个类?继承是OOP中的一个关键概念。唯一不好的继承是菱形继承。选项A或B都没有错。它们实现了不同的需求,尽管有重叠。我建议找一个A更好的机会,建立你的技能集,但要保持原样。选项C:只使用
BindingList
,不要使用包装器或继承类。只有当你对其中任何一个(额外的成员和功能)都有很好的理由时,你才能做出决定。但这不是你需要问自己的唯一问题。例如,编写预期的基类时是否考虑了继承?有很多类确实应该被密封,但实际上不是,并且类的编写方式不应该被继承(因为设计不够健壮)。如果它没有提供足够的方法来适当地修改继承者的行为(例如,让方法是虚拟的,并且让受保护的实现方法可以被重写),那么使用组合可能更好。@Sam I是的,有一个经典的例子可以质疑“是a”范式,正方形是四边形,但不应该继承它。
public class RowTypeHolder : BindingList<RowType>
{
    public event BeforeListChangedEventHandler BeforeListChanged;
    public delegate void BeforeListChangedEventHandler(RowTypeHolder sender, RowTypeHolderEventArgs e);

    public event AfterListChangedEventHandler AfterListChanged;
    public delegate void AfterListChangedEventHandler(RowTypeHolder sender, RowTypeHolderEventArgs e);

    public void OnBeforeListChanged(RowTypeHolderEventArgs.ChangeType change, string eventName)
    {
        if (this.BeforeListChanged != null)
            this.BeforeListChanged(this, new RowTypeHolderEventArgs(change, 0, eventName));
    }

    public void OnAfterListChanged(RowTypeHolderEventArgs.ChangeType change, int numChanges, string eventName)
    {
        if (this.AfterListChanged != null)
            this.AfterListChanged(this, new RowTypeHolderEventArgs(change, numChanges, eventName));
    }
}