简体   繁体   中英

Creating a collection of base class, then access properties of derived classes in the collection items

I have classes like this,

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

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

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

Now I have a collection class like this

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);
    }
}

I don't think that checking type of baseItem then casting is a very good practice, is it? Otherwise how do you suggest I solve this design problem?

Based on your code and comments, the correct approach would be to give Base a IsDuplicateOf method and override this in the derived classes. Something like this:

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;
    }
}

And you would use that method in your Add method:

public void Add(Base baseItem)
{
     if(items.Any(x => baseItem.IsDuplicateOf(x)))
         throw new DuplicateItemException(...);

     items.Add(baseItem);
}

Please note however, that this approach might become slow if there are many items in the list and the code inside IsDuplicateOf gets more complex.

You can't access derived class properties from base class without casting to the derived class first. However, in your case, you can do something different - instead of your current Add method, that takes a Base instance as a parameter, create a couple of Add method overloads, one for each derived class:

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM