创建基类集合,然后访问集合项中派生类的属性

时间:2017-12-20 12:21:00

标签: c# collections liskov-substitution-principle

我有这样的课程,

class Base
{
    int Id { get; set; }
}

class Derived1 : Base
{
    string DerivedProperty1 { get; set; }
}

class Derived2 : Base
{
    string DerivedProperty2 { get; set; }
}

现在我有一个像这样的集合类

public class MyCollection    
{
    List<Base> items;

    public void Add(Base baseItem)
    {
         // if baseItem is Derived1, if items contain an item of type Derived1 and has the same DerivedProperty1 value as baseItem, throw exception
         // if baseItem is Derived2, if items contain an item of type Derived2 and has the same DerivedProperty2 value as baseItem, throw exception
         items.Add(baseItem);
    }
}

我不认为检查类型的baseItem再铸造是一个非常好的做法,是吗?否则你怎么建议我解决这个设计问题?

2 个答案:

答案 0 :(得分:1)

根据您的代码和注释,正确的方法是给template一个Base方法,并在派生类中重写它。像这样:

IsDuplicateOf

您可以在class Base { int Id { get; set; } public virtual bool IsDuplicateOf(Base other) { return other != null && Id == other.Id; } } class Derived1 : Base { string DerivedProperty1 { get; set; } public override bool IsDuplicateOf(Base other) { return IsDuplicateOf(other as Derived1); } private bool IsDuplicateOf(Derived1 other) { return other != null && DerivedProperty1 == other.DerivedProperty1; } } class Derived2 : Base { string DerivedProperty2 { get; set; } public override bool IsDuplicateOf(Base other) { return IsDuplicateOf(other as Derived2); } private bool IsDuplicateOf(Derived2 other) { return other != null && DerivedProperty2 == other.DerivedProperty2; } } 方法中使用该方法:

Add

但请注意,如果列表中有许多项目且public void Add(Base baseItem) { if(items.Any(x => baseItem.IsDuplicateOf(x))) throw new DuplicateItemException(...); items.Add(baseItem); } 内的代码变得更复杂,则此方法可能会变慢。

答案 1 :(得分:1)

如果不首先转换为派生类,则无法从基类访问派生类属性。但是,在您的情况下,您可以执行不同的操作 - 而不是当前的Add方法,将Base实例作为参数,创建一些Add方法重载,一个用于每个派生类:

public void Add(Derived1 item)
{
    if(items.OfType<Derived1>().Any(i => i.DerivedProperty1 == item.DerivedProperty1)
        throw new InvalidOperationException("An item with the same DerivedProperty1 already exist"); 
     items.Add(baseItem);
}

public void Add(Derived2 item)
{
    if(items.OfType<Derived2>().Any(i => i.DerivedProperty2 == item.DerivedProperty2)
        throw new InvalidOperationException("An item with the same DerivedProperty2 already exist"); 
     items.Add(baseItem);
}