How to work with a list of base class, if a variable is only found in some subclasses?

Hi!
I’m new and I’m working on a small strategy game where I’m making different units. All my units derive from the Troop Class. The specific units can be three types that are subclasses of Troop: Living, Demon and Undead. These have further Subclasses, which are the specific kinds of units, such as Goblin : Living.

My problem is, that some subclasses have their own variables, such as Living has foodUse, that the others don’t have. When I try to loop through a List(Troop) looking for the amount of foodUse in each instance, it will give an error, that Troop doesn’t have a variable for foodUse. This is understandable, as the variable only exists in the Living subclass. Is there a way for such a loop to only look at instances of Troop that happen to have foodUse, and disregard instances that don’t? (While still using List(Troop) instead of List(Living) ?) Or maybe there’s just a better way of doing this than the subclassing I’m doing?
Thanks!

public abstract class Troop : UnitBase
{
    string[] _name;
    string[] _tags;
    int _type;
    int _hp;
    public DamageType damageType;
    public enum DamageType
    {
        Slashing,
        Piercing,
        Blunt,
        Magical,
    }
    
    public string[] name { get => _name; set => _name = value; }
    public string[] tags { get => _tags; set => _tags = value; }
    public int type { get => _type; set => _type = value; }
    public int hp { get => _hp; set => _hp = value; }
}

  public abstract class Living : Troop
    {
        float healMultiplier = 1f;
        public int foodUse;
    }
    
    public abstract class Demon : Troop
    {
        float healMultiplier = -1f;
        public int apetite;
    }
    
    public abstract class Undead : Troop
    {
        float healMultiplier = -0.5f;
    }

The specific unit types then inherit from these:

public class Goblin : Living
{      
    public Goblin(Alligeance thisalligeance)
    {
        alligeance = thisalligeance;
        name = new string[2] { "Goblin", "Goblins" };
        hp = 8;
        damageType =  DamageType.Blunt;
foodUse = 1;
    }
}

In other class:

   foreach (Troop unit in troops) { food -= unit.foodUse; } //Throws error, not all units have foodUse.

Hi! You should upcast the Troop object to a Living one:

Troop troop = //something
if(troop.IsInstanceOfType(Living)){ //Check if upcasting if possible, otherwise you'll get a runtime error!
Living living = (Living) troop; // Upcasting
living.foodUse = //access property
}

Check upcasting here

Hope this helps!

If you are using C# 7 you could use pattern matching:


foreach(var unit in troop)
{
    if (var unit is Living livingUnit)
    {
        livingUnit.foodUse // Use here
    }
}