2

This code works:

@page "/"
<button @onclick="@(()=>fun(0))" style="color: @style1[0]">
    Click me
</button>
<button @onclick="@(()=>fun(1))" style="color: @style1[1]">
    Click me
</button>
<button @onclick="@(()=>fun(2))" style="color: @style1[2]">
    Click me
</button>

@code{
    List<string> style1 = new List<string> { "black" , "black", "black" };
    void fun(int m)
    {
       try
       {
           if (style1[m] == "black") style1[m] = "red";
               else style1[m] = "black";
       }
       catch
       {
            Console.WriteLine("m = {0}", m);
       }
    }
}

But this one does not:

@page "/"
@for (int i = 0; i < 3; i++)
{
    <button @onclick="@(()=>fun(i))" style="color: @style1[i]">
        Click me
    </button>
}
@code{
//same as above
}

and this is the error in Console (without try-catch):

Unhandled exception rendering component: Index was out of range. Must be non-negative and less than the size of the collection.

after try-catch:

m = 3

Thanks

  • 2
    Try adding temporary variable inside the `for` loop and use it in `fun()`: `var tmp = i;` and `()=>fun(tmp)` – Guru Stron Feb 13 '21 at 07:55
  • Thank you very much. It worked. Could you please describe what is the difference between these statements and why did it not work? – Ebrahim Mehri Feb 13 '21 at 08:27
  • 1
    This is how [closures](https://stackoverflow.com/questions/35365350/closures-behaving-differently-in-for-and-foreach-loops) work in C#. – Guru Stron Feb 13 '21 at 09:08

1 Answers1

2

Take a look at the following code (a simpler version of your code in my index.razor)

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

@for (int i = 0; i < 3; i++)
{
    <button class="btn btn-primary mr-2" @onclick="(() => ButtonClick(i))">@($"Button {i}") </button>
}
<h4>Value = @value</h4>

@code {

    int value = -1;

    void ButtonClick(int x)
        => value = x;
}

Your expectation is that Value will display 1 when you click on Button 1. Not so, it always displays 3, the final value of i. The button click event submits the value of i when the button is clicked, the loop has long completed.

In your code i is 3 - the last version of i that stopped the for loop. - and m in style1[m] is 3 pointing to a none existent 4th member of style1. Index was out of range is quite correct, but quite as informative as it could be.

Sometimes you can't see the wood for the trees!!

MrC aka Shaun Curtis
  • 19,075
  • 3
  • 13
  • 31