Sisyphus
Sisyphus

Reputation: 910

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?

Upvotes: 0

Views: 309

Answers (2)

Zohar Peled
Zohar Peled

Reputation: 82504

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

Upvotes: 1

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174369

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.

Upvotes: 1

Related Questions