Have trouble adding Child classes to a List<Parent> .. Inventory stuff

I am working on my own inventory and for the most part I got it done in about 5-10 hours which watching and reading about after running into this problem I have seems kind of fast, so I assume I skipped a lot of corners and screwed myself and I think this might be it.

Problem:
I have a base class Item and an Inventory class that holds and manipulates a List of called Items. I want Items to accept all childrean of Item because the childrean are the only thing to ever be added. I have Equipment, Consumables, and Currency all Child classes of Item. Is there any way I could have a List or some other Collections class that can hold these 3 different types? I need access to their parent Item which holds the same basic info for all three (Name, Quantity, Sprites, … Ect) but the child holds the more crucial details like their effects, 2DArtwork, ect.
Visual Example:

Public Class Item{}
Public Class Equipment : Item {}
Public Class Consumable : Item {}

Inventory ()
{
    List<Item> items = new List<Item>();
    Equipment Helm = new Equipment ();
    List.add(Helm);
    Consumable Potion = new Consumable();
    List.add(Potion);
}

OR… Maybe there is a better way to go about what I am trying to do? I’ve looked at so much and learned a lot of new things about C# and Unity, but none of which helps me currently. I also thought about adding ALL information for each class into Item class and access what I want by a type variable… but I really want this way to work.

If they all inherit from Item, it should be fine to do it that way. You’ll probably just have to check type and cast to the appropriate inherited class when accessing an item from that list, then.

I would say what you’re doing is actually the “correct” way, or at least as far as I can tell. So you’re learning more than you give yourself credit for.

I just tried casting the selected Item as Equipment and it works! I am beyond happy right now. I can literally pick right back up from where I left off and not have to change a thing. Thank you so much for your kind words and advice!

1 Like

I’m not 100% sure what you are trying to do or how your setup looks like.

But I guess the System.Linq namespace can help you a lot here.
If you want to iterate through all the Equipments for example you could write a method like this:

IEnumerable<Equipment> GetEquipments()
{
    foreach(Item itm in items)
    {
        if(itm is Equipment)
            yield return itm as Equipment;
    }
}

then you can iterate through all equipments like this:

foreach(Equipment equip in GetEquipments())
{
    // do something with equip
}

you could refine the method to support any kind of Item like this:

IEnumerable<T> GetItemsOfType<T>()
    where T : Item
{
    foreach(Item itm in items)
    {
        if(itm is T)
            yield return (T)itm;
    }
}

now you also could iterate through the consumables:

foreach(Consumable c in GetItemsOfType<Consumable>())
{
    // do something with c
}

IEnumerables are cool interfaces which enables you to iterate through with a foreach loop. On that interface is most of the stuff of the System.Linq namespace depending. All the Collections (like Lists) also implement IEnumerable, so you can work on them with Linq.

the last example could also be done without an own method (but with linq):

using System.Linq;
// ...
foreach(Consumable c in items.OfType<Consumable>())
{
    // do something with c
}

there are a lot more System.Linq methods which can come in handy.
Here a small list of the most used ones (please research by yourself):

  • Where
  • Select
  • First / FirstOrDefault
  • Last / LastOrDefault

Linq is a great addition to C#. But it is not the fastest. It always starts to loop through the elements and most of the methods iterate through all the elements. So it is faster if you would have a separate list for each item type.
But if you don’t have thousands of items (and if you don’t need to filter it every few frames) the System.Linq approach is probably fast enough for your needs.