0

I don't really know how to explain this but i have tried a few thing and they don't work. Basically i want to have an Action on a item, the action is kinda like the items functionality. here is my code it's not that advanced.

class Item
{
    private int itemCount;
    private Action itemUsage;
    string name;

    //Item.Item()
    public Item(string _name, Action _itemUsage, int _itemCount)
    {
        name = _name;
        itemUsage = _itemUsage;
        itemCount = _itemCount;

        //laterInvokes itemUsage
    }

    //Item.UseItem
    public void UseItem()
    {
        //TYPE:ACTION, is set in constructor
        this.itemUsage();
    }
}

And.

class Program
{
    //Program.Main(string[] args)
    public static void Main(string[] args)
    {
        Item[] items = new Item[11];

        //for every item in items;
        for (int i = 0; i < items.Length; i++)
        {
            //How do i save 'a's lambda with out it coming back here?
            Action a = () => Console.WriteLine("Used Item " + i);
            items[i] = new Item("Item " + i, a, 1);
        }

        items[0].UseItem();
        items[3].UseItem();
        items[4].UseItem();
        items[7].UseItem();
        //Expect result;
        //"Used Item 0"
        //"Used Item 2"
        //"Used Item 3"
        //"Used Item 7"

        //Actual Result
        //"Used Item 5"
        //"Used Item 5"
        //"Used Item 5"
        //"Used Item 5"

        Console.ReadLine();
    }


}

The problem as i can see it is that the i variable is not saved in the lambda.

Action a = () => Console.WriteLine("Used Item " + i);

so whenever i call item[x].UseItem() it goes back inside the for loop to the Action a declaration and 'uses' the i there which is now 5.

1 Answers1

1

If you run your code, you don't get Used Item 5, but this:

Used Item 11
Used Item 11
Used Item 11
Used Item 11

and this is expected, since items.Length is equal to 11.

Every time the code compiles

Action a = () => Console.WriteLine("Used Item " + i);

a gets "updated" with Console.WriteLine("Used Item " + i); with the current i of the for loop, its last value is 11, so at the end of the loop you have

a = () => Console.WriteLine("Used Item " + 11);

for every a defined.

In order to avoid this (common) mistake, you need to implement a temporary variable, as suggested by Rand Random:

var temp = i;
Action a = () => Console.WriteLine("Used Item " + temp);
Galandil
  • 4,169
  • 1
  • 13
  • 24