Home > Software engineering >  How to update one element of a list without updating all elements in C#?
How to update one element of a list without updating all elements in C#?

Time:08-07

I'm struggling with one piece of code and I was wondering if anyone could help me.

Here's my problem:

I'm working on a game and I created an inventory with a Dictionary. My Dictionary TKey is the item name and the TValue is a List. Each items has a boolean "isEquipped".

Dictionary<string, List<Item>> itemsInventory;

When equipping an item I want to check if the player has enough of this item and if this item can be equipped. I do that with this code:

public void EquipWeapon(bool tog, Item item)
{
    if (tog == true)
    {
        if (player.weapon == false)
        {
            player.GetStatByName(item.StatAffectedName).AddModifier(item.StatAffectedValue, StatModifier.ModifierOrigins.Equipment, StatModifier.ModifierType.Flat, item.AssetName);
            GameManagerSingleton.Instance.PlayerData.itemsInventory.FirstOrDefault(x => x.Key == item.AssetName && x.Value.Any(x => x.isEquiped == false)).Value.FirstOrDefault().isEquiped = true;
        }
    }
    else
    {
        if (player.weapon == true)
        {
            player.GetStatByName(item.StatAffectedName).RemoveModifier(item.AssetName);
            GameManagerSingleton.Instance.PlayerData.itemsInventory.FirstOrDefault(x => x.Key == item.AssetName && x.Value.Any(x => x.isEquiped == true)).Value.FirstOrDefault().isEquiped = false;
        }
        player.weapon = false;
    }
    player.GetStatByName(item.StatAffectedName).GetValue();
}

Problem with my code is that it changes all the items of the list and not just one. Anyone could help me please?

CodePudding user response:

From the comment you made "If I update in the debugger it change all items as well." it seems that the values in the list are the same object. This strongly suggests that Item is a class (not a struct).

You need to clone the objects before adding them to the list if they represent different instances.

From List View

List's item detail

After I changed from false to true not only the item at index 0 but all objects changes.

CodePudding user response:

When I create the player, I create the Dictionary like this:

itemsInventory = new Dictionary<string, List<Item>>(),

And when I create the list it's like this:

Instance.PlayerData.itemsInventory.Add("weapon", new List<Item>());
Instance.PlayerData.itemsInventory.Add("armour", new List<Item>());
Instance.PlayerData.itemsInventory.Add("shield", new List<Item>());

CodePudding user response:

My code looked like this :

public void AddItemToInventory(Item? item, Ressource? ressource, int number = 1)
    {
        if (item != null)
        {
            int totalPrice = (item.Price * number);
            ressources.First(x => x.currency == item.Currency).amount -= totalPrice;
            DailyReportHandler.GetAndFillTodayReport().moneyForItems  = totalPrice;
            if (itemsInventory.ContainsKey(item.AssetName))
            {
                for (int i = 0; i < number; i  )
                {
                    itemsInventory.FirstOrDefault(x => x.Key == item.AssetName).Value.Add(item);
                }
            }
            else
            {
                itemsInventory.Add(item.AssetName, new List<Item>());
                for (int i = 0; i < number; i  )
                {
                    itemsInventory.FirstOrDefault(x => x.Key == item.AssetName).Value.Add(item);
                }
            }
        }
        if (ressource != null)
        {
            int totalPrice = (ressource.price * number);
            ressources.First(x => x.currency == Currency.credit).amount -= totalPrice;
            DailyReportHandler.GetAndFillTodayReport().moneyForItems  = totalPrice;
            GameManagerSingleton.Instance.PlayerData.AddResource(ressource.currency, number);
        }
    }

and I change it to this:

public void AddItemToInventory(Item? item, Ressource? ressource, int number = 1)
    {
        if (item != null)
        {
            int totalPrice = (item.Price * number);
            ressources.First(x => x.currency == item.Currency).amount -= totalPrice;
            DailyReportHandler.GetAndFillTodayReport().moneyForItems  = totalPrice;
            if (itemsInventory.ContainsKey(item.AssetName))
            {
                for (int i = 0; i < number; i  )
                {
                    itemsInventory.FirstOrDefault(x => x.Key == item.AssetName).Value.Add(GenerateNewItem(item));
                }
            }
            else
            {
                itemsInventory.Add(item.AssetName, new List<Item>());
                for (int i = 0; i < number; i  )
                {
                    itemsInventory.FirstOrDefault(x => x.Key == item.AssetName).Value.Add(GenerateNewItem(item));
                }
            }
        }
        if (ressource != null)
        {
            int totalPrice = (ressource.price * number);
            ressources.First(x => x.currency == Currency.credit).amount -= totalPrice;
            DailyReportHandler.GetAndFillTodayReport().moneyForItems  = totalPrice;
            GameManagerSingleton.Instance.PlayerData.AddResource(ressource.currency, number);
        }
    }

With GenerateNewItem(item) like this:

public Item GenerateNewItem(Item item)
    {
        var newItem = new Item
        {
            AssetName = item.AssetName,
            Currency = item.Currency,
            DescriptionLocalizationKey = item.AssetName,
            isEquiped = false,
            itemType = item.itemType,
            NameLocalizationKey = item.NameLocalizationKey,
            Price = item.Price,
            ShortDescriptionLocalizationKey = item.ShortDescriptionLocalizationKey,
            StatAffectedName = item.StatAffectedName,
            StatAffectedValue = item.StatAffectedValue
        };
        return newItem;
    }
  • Related