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
}