Home > database >  C# how to use child method in object type dictionary
C# how to use child method in object type dictionary

Time:09-30

I have a dictionary of Lists with types (Weapon, Armour, Potion) that extended from 1 parent (Item), in a child classes GetItemData overrides with different properties

internal abstract class Item
{
    protected string name = "Item";
    protected int level = GameConstants.MIN_ITEM_LEVEL;
    protected string description = "";
    protected Types type;

    public enum Types
    {
        armour, potion, weapon
    }

    public Dictionary<string, dynamic> GetItemData()
    {
        return new Dictionary<string, dynamic>() {
            { "name",  name},
            { "description", description },
            { "type", type }
        };
    }

}
//dictionary in player class
protected Dictionary<string, object> inventory
        = new()
        {
            {"WEAPON", new List<Weapon>() },
            {"AMOUR", new List<Armour>() },
            {"POTION", new List<Potion>() }
            //All are extended from Item `class Weapon:Item`
        };

I need to show some data from each list to user, for this i create a function that takes a itemSelector for dictionary, and Write data from them to console. But function that i write is not work, its throw

System.InvalidCastException: "Unable to cast object of type 'System.Collections.Generic.List1[Items.Weapon.Weapon]' to type 'System.Collections.Generic.List1[Items.Item]'."

private void ListPlayerItems(string previewText, string itemSelector)
    {
        Console.WriteLine(previewText);
        int itemIndex = 0;

        ((List<Item>)inventory[itemSelector]).ForEach(item =>
        {

            Dictionary<string, dynamic> itemData = item.GetItemData();
            Console.Write($"{itemIndex}) Название: {itemData["name"]}; Описание:{itemData["description"]}; ");
            if (item is Weapon)
            {
                Console.Write($"Минимальный урон: {itemData["minDamage"]}; Максимальный урон: {itemData["maxDamage"]}\n");
            }


            itemIndex  ;
        });
    }

The problem is in Type that takes a List<> in implicit operator

     ((List<Item>)inventory[itemSelector]).ForEach(item =>

As i get it, i need somehow downcast Item to type of picked List, i dont know how to do that, please help me with that, maybe i make it wrong from start and you know better way to do this

CodePudding user response:

C# does not support variance for classes (see this and this), so List<Item> is not List<Weapon> even if Item is base class for Weapon. For this particular use case you can workaround with non-generic IEnumerable, OfType and ordinary foreach:

foreach(var item in inventory[itemSelector].OfType<Item>())
{
   // ...use item
}
  • Related