Captured variable in a loop in C#












184















I met an interesting issue about C#. I have code like below.



List<Func<int>> actions = new List<Func<int>>();

int variable = 0;
while (variable < 5)
{
actions.Add(() => variable * 2);
++ variable;
}

foreach (var act in actions)
{
Console.WriteLine(act.Invoke());
}


I expect it to output 0, 2, 4, 6, 8. However, it actually outputs five 10s.



It seems that it is due to all actions referring to one captured variable. As a result, when they get invoked, they all have same output.



Is there a way to work round this limit to have each action instance have its own captured variable?










share|improve this question




















  • 12





    See also Eric Lippert's Blog series on the subject: Closing over the Loop Variable Considered Harmful

    – Brian
    Nov 11 '10 at 21:50








  • 8





    Also, they are changing C# 5 to work as you expect within a foreach. (breaking change)

    – Neal Tibrewala
    Mar 4 '12 at 18:55






  • 1





    Related: why-is-it-bad-to-use-an-iteration-variable-in-a-lambda-expression

    – nawfal
    Nov 2 '13 at 7:08






  • 1





    @Neal: although this example still doesn't work properly in C# 5, as it still outputs five 10s

    – Ian Oakes
    Feb 6 '14 at 5:41






  • 3





    It verified that it outputs five 10s till today on C# 6.0 (VS 2015). I doubt that this behavior of closure variables is a candidate for change. Captured variables are always evaluated when the delegate is actually invoked, not when the variables were captured.

    – RBT
    Apr 22 '17 at 3:03


















184















I met an interesting issue about C#. I have code like below.



List<Func<int>> actions = new List<Func<int>>();

int variable = 0;
while (variable < 5)
{
actions.Add(() => variable * 2);
++ variable;
}

foreach (var act in actions)
{
Console.WriteLine(act.Invoke());
}


I expect it to output 0, 2, 4, 6, 8. However, it actually outputs five 10s.



It seems that it is due to all actions referring to one captured variable. As a result, when they get invoked, they all have same output.



Is there a way to work round this limit to have each action instance have its own captured variable?










share|improve this question




















  • 12





    See also Eric Lippert's Blog series on the subject: Closing over the Loop Variable Considered Harmful

    – Brian
    Nov 11 '10 at 21:50








  • 8





    Also, they are changing C# 5 to work as you expect within a foreach. (breaking change)

    – Neal Tibrewala
    Mar 4 '12 at 18:55






  • 1





    Related: why-is-it-bad-to-use-an-iteration-variable-in-a-lambda-expression

    – nawfal
    Nov 2 '13 at 7:08






  • 1





    @Neal: although this example still doesn't work properly in C# 5, as it still outputs five 10s

    – Ian Oakes
    Feb 6 '14 at 5:41






  • 3





    It verified that it outputs five 10s till today on C# 6.0 (VS 2015). I doubt that this behavior of closure variables is a candidate for change. Captured variables are always evaluated when the delegate is actually invoked, not when the variables were captured.

    – RBT
    Apr 22 '17 at 3:03
















184












184








184


48






I met an interesting issue about C#. I have code like below.



List<Func<int>> actions = new List<Func<int>>();

int variable = 0;
while (variable < 5)
{
actions.Add(() => variable * 2);
++ variable;
}

foreach (var act in actions)
{
Console.WriteLine(act.Invoke());
}


I expect it to output 0, 2, 4, 6, 8. However, it actually outputs five 10s.



It seems that it is due to all actions referring to one captured variable. As a result, when they get invoked, they all have same output.



Is there a way to work round this limit to have each action instance have its own captured variable?










share|improve this question
















I met an interesting issue about C#. I have code like below.



List<Func<int>> actions = new List<Func<int>>();

int variable = 0;
while (variable < 5)
{
actions.Add(() => variable * 2);
++ variable;
}

foreach (var act in actions)
{
Console.WriteLine(act.Invoke());
}


I expect it to output 0, 2, 4, 6, 8. However, it actually outputs five 10s.



It seems that it is due to all actions referring to one captured variable. As a result, when they get invoked, they all have same output.



Is there a way to work round this limit to have each action instance have its own captured variable?







c# closures captured-variable






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 17 '14 at 18:43









Peter Mortensen

13.8k1987113




13.8k1987113










asked Nov 7 '08 at 7:26









Morgan ChengMorgan Cheng

28.7k54151212




28.7k54151212








  • 12





    See also Eric Lippert's Blog series on the subject: Closing over the Loop Variable Considered Harmful

    – Brian
    Nov 11 '10 at 21:50








  • 8





    Also, they are changing C# 5 to work as you expect within a foreach. (breaking change)

    – Neal Tibrewala
    Mar 4 '12 at 18:55






  • 1





    Related: why-is-it-bad-to-use-an-iteration-variable-in-a-lambda-expression

    – nawfal
    Nov 2 '13 at 7:08






  • 1





    @Neal: although this example still doesn't work properly in C# 5, as it still outputs five 10s

    – Ian Oakes
    Feb 6 '14 at 5:41






  • 3





    It verified that it outputs five 10s till today on C# 6.0 (VS 2015). I doubt that this behavior of closure variables is a candidate for change. Captured variables are always evaluated when the delegate is actually invoked, not when the variables were captured.

    – RBT
    Apr 22 '17 at 3:03
















  • 12





    See also Eric Lippert's Blog series on the subject: Closing over the Loop Variable Considered Harmful

    – Brian
    Nov 11 '10 at 21:50








  • 8





    Also, they are changing C# 5 to work as you expect within a foreach. (breaking change)

    – Neal Tibrewala
    Mar 4 '12 at 18:55






  • 1





    Related: why-is-it-bad-to-use-an-iteration-variable-in-a-lambda-expression

    – nawfal
    Nov 2 '13 at 7:08






  • 1





    @Neal: although this example still doesn't work properly in C# 5, as it still outputs five 10s

    – Ian Oakes
    Feb 6 '14 at 5:41






  • 3





    It verified that it outputs five 10s till today on C# 6.0 (VS 2015). I doubt that this behavior of closure variables is a candidate for change. Captured variables are always evaluated when the delegate is actually invoked, not when the variables were captured.

    – RBT
    Apr 22 '17 at 3:03










12




12





See also Eric Lippert's Blog series on the subject: Closing over the Loop Variable Considered Harmful

– Brian
Nov 11 '10 at 21:50







See also Eric Lippert's Blog series on the subject: Closing over the Loop Variable Considered Harmful

– Brian
Nov 11 '10 at 21:50






8




8





Also, they are changing C# 5 to work as you expect within a foreach. (breaking change)

– Neal Tibrewala
Mar 4 '12 at 18:55





Also, they are changing C# 5 to work as you expect within a foreach. (breaking change)

– Neal Tibrewala
Mar 4 '12 at 18:55




1




1





Related: why-is-it-bad-to-use-an-iteration-variable-in-a-lambda-expression

– nawfal
Nov 2 '13 at 7:08





Related: why-is-it-bad-to-use-an-iteration-variable-in-a-lambda-expression

– nawfal
Nov 2 '13 at 7:08




1




1





@Neal: although this example still doesn't work properly in C# 5, as it still outputs five 10s

– Ian Oakes
Feb 6 '14 at 5:41





@Neal: although this example still doesn't work properly in C# 5, as it still outputs five 10s

– Ian Oakes
Feb 6 '14 at 5:41




3




3





It verified that it outputs five 10s till today on C# 6.0 (VS 2015). I doubt that this behavior of closure variables is a candidate for change. Captured variables are always evaluated when the delegate is actually invoked, not when the variables were captured.

– RBT
Apr 22 '17 at 3:03







It verified that it outputs five 10s till today on C# 6.0 (VS 2015). I doubt that this behavior of closure variables is a candidate for change. Captured variables are always evaluated when the delegate is actually invoked, not when the variables were captured.

– RBT
Apr 22 '17 at 3:03














8 Answers
8






active

oldest

votes


















166














Yes - take a copy of the variable inside the loop:



while (variable < 5)
{
int copy = variable;
actions.Add(() => copy * 2);
++ variable;
}


You can think of it as if the C# compiler creates a "new" local variable every time it hits the variable declaration. In fact it'll create appropriate new closure objects, and it gets complicated (in terms of implementation) if you refer to variables in multiple scopes, but it works :)



Note that a more common occurrence of this problem is using for or foreach:



for (int i=0; i < 10; i++) // Just one variable
foreach (string x in foo) // And again, despite how it reads out loud


See section 7.14.4.2 of the C# 3.0 spec for more details of this, and my article on closures has more examples too.






share|improve this answer





















  • 26





    Jon's book also has a very good chapter on this (stop being humble, Jon!)

    – Marc Gravell
    Nov 7 '08 at 7:57






  • 29





    It looks better if I let other people plug it ;) (I confess that I do tend to vote up answers recommending it though.)

    – Jon Skeet
    Nov 7 '08 at 8:03






  • 2





    As ever, feedback to skeet@pobox.com would be appreciated :)

    – Jon Skeet
    Nov 7 '08 at 9:30






  • 6





    For C# 5.0 behavior is different (more reasonable) see newer answer by Jon Skeet - stackoverflow.com/questions/16264289/…

    – Alexei Levenkov
    Jan 22 '16 at 2:35





















19














I believe what you are experiencing is something known as Closure http://en.wikipedia.org/wiki/Closure_(computer_science). Your lamba has a reference to a variable which is scoped outside the function itself. Your lamba is not interpreted until you invoke it and once it is it will get the value the variable has at execution time.






share|improve this answer































    9














    Behind the scenes, the compiler is generating a class that represents the closure for your method call. It uses that single instance of the closure class for each iteration of the loop. The code looks something like this, which makes it easier to see why the bug happens:



    void Main()
    {
    List<Func<int>> actions = new List<Func<int>>();

    int variable = 0;

    var closure = new CompilerGeneratedClosure();

    Func<int> anonymousMethodAction = null;

    while (closure.variable < 5)
    {
    if(anonymousMethodAction == null)
    anonymousMethodAction = new Func<int>(closure.YourAnonymousMethod);

    //we're re-adding the same function
    actions.Add(anonymousMethodAction);

    ++closure.variable;
    }

    foreach (var act in actions)
    {
    Console.WriteLine(act.Invoke());
    }
    }

    class CompilerGeneratedClosure
    {
    public int variable;

    public int YourAnonymousMethod()
    {
    return this.variable * 2;
    }
    }


    This isn't actually the compiled code from your sample, but I've examined my own code and this looks very much like what the compiler would actually generate.






    share|improve this answer

































      7














      The way around this is to store the value you need in a proxy variable, and have that variable get captured.



      I.E.



      while( variable < 5 )
      {
      int copy = variable;
      actions.Add( () => copy * 2 );
      ++variable;
      }





      share|improve this answer



















      • 1





        Yeah, it works. But, why?

        – Morgan Cheng
        Nov 7 '08 at 7:34











      • See the explanation in my edited answer. I'm finding the relevant bit of the spec now.

        – Jon Skeet
        Nov 7 '08 at 7:35











      • Haha jon, I actually just read your article: csharpindepth.com/Articles/Chapter5/Closures.aspx You do good work my friend.

        – tjlevine
        Nov 7 '08 at 7:36











      • @tjlevine: Thanks very much. I'll add a reference to that in my answer. I'd forgotten about it!

        – Jon Skeet
        Nov 7 '08 at 7:37











      • Also, Jon, I'd love to read about your thoughts on the various Java 7 closure proposals. I've seen you mention that you wanted to write one, but I haven't seen it.

        – tjlevine
        Nov 7 '08 at 7:42



















      4














      Yes you need to scope variable within the loop and pass it to the lambda that way:



      List<Func<int>> actions = new List<Func<int>>();

      int variable = 0;
      while (variable < 5)
      {
      int variable1 = variable;
      actions.Add(() => variable1 * 2);
      ++variable;
      }

      foreach (var act in actions)
      {
      Console.WriteLine(act.Invoke());
      }

      Console.ReadLine();





      share|improve this answer































        4














        The same situation is happening in multi-threading (C#, .NET 4.0].



        See the following code:



        Purpose is to print 1,2,3,4,5 in order.



        for (int counter = 1; counter <= 5; counter++)
        {
        new Thread (() => Console.Write (counter)).Start();
        }


        The output is interesting! (It might be like 21334...)



        The only solution is to use local variables.



        for (int counter = 1; counter <= 5; counter++)
        {
        int localVar= counter;
        new Thread (() => Console.Write (localVar)).Start();
        }





        share|improve this answer


























        • This does not seem to help me. Still non-deterministic.

          – Mladen Mihajlovic
          Jan 31 '14 at 11:14



















        3














        This has nothing to do with loops.



        This behavior is triggered because you use a lambda expression () => variable * 2 where the outer scoped variable not actually defined in the lambda's inner scope.



        Lambda expressions (in C#3+, as well as anonymous methods in C#2) still create actual methods. Passing variables to these methods involve some dilemmas (pass by value? pass by reference? C# goes with by reference - but this opens another problem where the reference can outlive the actual variable). What C# does to resolve all these dilemmas is to create a new helper class ("closure") with fields corresponding to the local variables used in the lambda expressions, and methods corresponding to the actual lambda methods. Any changes to variable in your code is actually translated to change in that ClosureClass.variable



        So your while loop keeps updating the ClosureClass.variable until it reaches 10, then you for loops executes the actions, which all operate on the same ClosureClass.variable.



        To get your expected result, you need to create a separation between the loop variable, and the variable that is being closured. You can do this by introducing another variable, i.e.:



        List<Func<int>> actions = new List<Func<int>>();
        int variable = 0;
        while (variable < 5)
        {
        var t = variable; // now t will be closured (i.e. replaced by a field in the new class)
        actions.Add(() => t * 2);
        ++variable; // changing variable won't affect the closured variable t
        }
        foreach (var act in actions)
        {
        Console.WriteLine(act.Invoke());
        }


        You could also move the closure to another method to create this separation:



        List<Func<int>> actions = new List<Func<int>>();

        int variable = 0;
        while (variable < 5)
        {
        actions.Add(Mult(variable));
        ++variable;
        }

        foreach (var act in actions)
        {
        Console.WriteLine(act.Invoke());
        }


        You can implement Mult as a lambda expression (implicit closure)



        static Func<int> Mult(int i)
        {
        return () => i * 2;
        }


        or with an actual helper class:



        public class Helper
        {
        public int _i;
        public Helper(int i)
        {
        _i = i;
        }
        public int Method()
        {
        return _i * 2;
        }
        }

        static Func<int> Mult(int i)
        {
        Helper help = new Helper(i);
        return help.Method;
        }


        In any case, "Closures" are NOT a concept related to loops, but rather to anonymous methods / lambda expressions use of local scoped variables - although some incautious use of loops demonstrate closures traps.






        share|improve this answer

































          0














          It is called the closure problem,
          simply use a copy variable, and it's done.



          List<Func<int>> actions = new List<Func<int>>();

          int variable = 0;
          while (variable < 5)
          {
          int i = variable;
          actions.Add(() => i * 2);
          ++ variable;
          }

          foreach (var act in actions)
          {
          Console.WriteLine(act.Invoke());
          }





          share|improve this answer



















          • 1





            In what way your answer is different from the answer provided by someone above?

            – Thangadurai
            Jan 30 at 7:38










          protected by Elenasys Jan 6 '14 at 22:10



          Thank you for your interest in this question.
          Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



          Would you like to answer one of these unanswered questions instead?














          8 Answers
          8






          active

          oldest

          votes








          8 Answers
          8






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          166














          Yes - take a copy of the variable inside the loop:



          while (variable < 5)
          {
          int copy = variable;
          actions.Add(() => copy * 2);
          ++ variable;
          }


          You can think of it as if the C# compiler creates a "new" local variable every time it hits the variable declaration. In fact it'll create appropriate new closure objects, and it gets complicated (in terms of implementation) if you refer to variables in multiple scopes, but it works :)



          Note that a more common occurrence of this problem is using for or foreach:



          for (int i=0; i < 10; i++) // Just one variable
          foreach (string x in foo) // And again, despite how it reads out loud


          See section 7.14.4.2 of the C# 3.0 spec for more details of this, and my article on closures has more examples too.






          share|improve this answer





















          • 26





            Jon's book also has a very good chapter on this (stop being humble, Jon!)

            – Marc Gravell
            Nov 7 '08 at 7:57






          • 29





            It looks better if I let other people plug it ;) (I confess that I do tend to vote up answers recommending it though.)

            – Jon Skeet
            Nov 7 '08 at 8:03






          • 2





            As ever, feedback to skeet@pobox.com would be appreciated :)

            – Jon Skeet
            Nov 7 '08 at 9:30






          • 6





            For C# 5.0 behavior is different (more reasonable) see newer answer by Jon Skeet - stackoverflow.com/questions/16264289/…

            – Alexei Levenkov
            Jan 22 '16 at 2:35


















          166














          Yes - take a copy of the variable inside the loop:



          while (variable < 5)
          {
          int copy = variable;
          actions.Add(() => copy * 2);
          ++ variable;
          }


          You can think of it as if the C# compiler creates a "new" local variable every time it hits the variable declaration. In fact it'll create appropriate new closure objects, and it gets complicated (in terms of implementation) if you refer to variables in multiple scopes, but it works :)



          Note that a more common occurrence of this problem is using for or foreach:



          for (int i=0; i < 10; i++) // Just one variable
          foreach (string x in foo) // And again, despite how it reads out loud


          See section 7.14.4.2 of the C# 3.0 spec for more details of this, and my article on closures has more examples too.






          share|improve this answer





















          • 26





            Jon's book also has a very good chapter on this (stop being humble, Jon!)

            – Marc Gravell
            Nov 7 '08 at 7:57






          • 29





            It looks better if I let other people plug it ;) (I confess that I do tend to vote up answers recommending it though.)

            – Jon Skeet
            Nov 7 '08 at 8:03






          • 2





            As ever, feedback to skeet@pobox.com would be appreciated :)

            – Jon Skeet
            Nov 7 '08 at 9:30






          • 6





            For C# 5.0 behavior is different (more reasonable) see newer answer by Jon Skeet - stackoverflow.com/questions/16264289/…

            – Alexei Levenkov
            Jan 22 '16 at 2:35
















          166












          166








          166







          Yes - take a copy of the variable inside the loop:



          while (variable < 5)
          {
          int copy = variable;
          actions.Add(() => copy * 2);
          ++ variable;
          }


          You can think of it as if the C# compiler creates a "new" local variable every time it hits the variable declaration. In fact it'll create appropriate new closure objects, and it gets complicated (in terms of implementation) if you refer to variables in multiple scopes, but it works :)



          Note that a more common occurrence of this problem is using for or foreach:



          for (int i=0; i < 10; i++) // Just one variable
          foreach (string x in foo) // And again, despite how it reads out loud


          See section 7.14.4.2 of the C# 3.0 spec for more details of this, and my article on closures has more examples too.






          share|improve this answer















          Yes - take a copy of the variable inside the loop:



          while (variable < 5)
          {
          int copy = variable;
          actions.Add(() => copy * 2);
          ++ variable;
          }


          You can think of it as if the C# compiler creates a "new" local variable every time it hits the variable declaration. In fact it'll create appropriate new closure objects, and it gets complicated (in terms of implementation) if you refer to variables in multiple scopes, but it works :)



          Note that a more common occurrence of this problem is using for or foreach:



          for (int i=0; i < 10; i++) // Just one variable
          foreach (string x in foo) // And again, despite how it reads out loud


          See section 7.14.4.2 of the C# 3.0 spec for more details of this, and my article on closures has more examples too.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 7 '08 at 7:37

























          answered Nov 7 '08 at 7:32









          Jon SkeetJon Skeet

          1095k69679818467




          1095k69679818467








          • 26





            Jon's book also has a very good chapter on this (stop being humble, Jon!)

            – Marc Gravell
            Nov 7 '08 at 7:57






          • 29





            It looks better if I let other people plug it ;) (I confess that I do tend to vote up answers recommending it though.)

            – Jon Skeet
            Nov 7 '08 at 8:03






          • 2





            As ever, feedback to skeet@pobox.com would be appreciated :)

            – Jon Skeet
            Nov 7 '08 at 9:30






          • 6





            For C# 5.0 behavior is different (more reasonable) see newer answer by Jon Skeet - stackoverflow.com/questions/16264289/…

            – Alexei Levenkov
            Jan 22 '16 at 2:35
















          • 26





            Jon's book also has a very good chapter on this (stop being humble, Jon!)

            – Marc Gravell
            Nov 7 '08 at 7:57






          • 29





            It looks better if I let other people plug it ;) (I confess that I do tend to vote up answers recommending it though.)

            – Jon Skeet
            Nov 7 '08 at 8:03






          • 2





            As ever, feedback to skeet@pobox.com would be appreciated :)

            – Jon Skeet
            Nov 7 '08 at 9:30






          • 6





            For C# 5.0 behavior is different (more reasonable) see newer answer by Jon Skeet - stackoverflow.com/questions/16264289/…

            – Alexei Levenkov
            Jan 22 '16 at 2:35










          26




          26





          Jon's book also has a very good chapter on this (stop being humble, Jon!)

          – Marc Gravell
          Nov 7 '08 at 7:57





          Jon's book also has a very good chapter on this (stop being humble, Jon!)

          – Marc Gravell
          Nov 7 '08 at 7:57




          29




          29





          It looks better if I let other people plug it ;) (I confess that I do tend to vote up answers recommending it though.)

          – Jon Skeet
          Nov 7 '08 at 8:03





          It looks better if I let other people plug it ;) (I confess that I do tend to vote up answers recommending it though.)

          – Jon Skeet
          Nov 7 '08 at 8:03




          2




          2





          As ever, feedback to skeet@pobox.com would be appreciated :)

          – Jon Skeet
          Nov 7 '08 at 9:30





          As ever, feedback to skeet@pobox.com would be appreciated :)

          – Jon Skeet
          Nov 7 '08 at 9:30




          6




          6





          For C# 5.0 behavior is different (more reasonable) see newer answer by Jon Skeet - stackoverflow.com/questions/16264289/…

          – Alexei Levenkov
          Jan 22 '16 at 2:35







          For C# 5.0 behavior is different (more reasonable) see newer answer by Jon Skeet - stackoverflow.com/questions/16264289/…

          – Alexei Levenkov
          Jan 22 '16 at 2:35















          19














          I believe what you are experiencing is something known as Closure http://en.wikipedia.org/wiki/Closure_(computer_science). Your lamba has a reference to a variable which is scoped outside the function itself. Your lamba is not interpreted until you invoke it and once it is it will get the value the variable has at execution time.






          share|improve this answer




























            19














            I believe what you are experiencing is something known as Closure http://en.wikipedia.org/wiki/Closure_(computer_science). Your lamba has a reference to a variable which is scoped outside the function itself. Your lamba is not interpreted until you invoke it and once it is it will get the value the variable has at execution time.






            share|improve this answer


























              19












              19








              19







              I believe what you are experiencing is something known as Closure http://en.wikipedia.org/wiki/Closure_(computer_science). Your lamba has a reference to a variable which is scoped outside the function itself. Your lamba is not interpreted until you invoke it and once it is it will get the value the variable has at execution time.






              share|improve this answer













              I believe what you are experiencing is something known as Closure http://en.wikipedia.org/wiki/Closure_(computer_science). Your lamba has a reference to a variable which is scoped outside the function itself. Your lamba is not interpreted until you invoke it and once it is it will get the value the variable has at execution time.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Nov 7 '08 at 7:34









              TheCodeJunkieTheCodeJunkie

              6,97273552




              6,97273552























                  9














                  Behind the scenes, the compiler is generating a class that represents the closure for your method call. It uses that single instance of the closure class for each iteration of the loop. The code looks something like this, which makes it easier to see why the bug happens:



                  void Main()
                  {
                  List<Func<int>> actions = new List<Func<int>>();

                  int variable = 0;

                  var closure = new CompilerGeneratedClosure();

                  Func<int> anonymousMethodAction = null;

                  while (closure.variable < 5)
                  {
                  if(anonymousMethodAction == null)
                  anonymousMethodAction = new Func<int>(closure.YourAnonymousMethod);

                  //we're re-adding the same function
                  actions.Add(anonymousMethodAction);

                  ++closure.variable;
                  }

                  foreach (var act in actions)
                  {
                  Console.WriteLine(act.Invoke());
                  }
                  }

                  class CompilerGeneratedClosure
                  {
                  public int variable;

                  public int YourAnonymousMethod()
                  {
                  return this.variable * 2;
                  }
                  }


                  This isn't actually the compiled code from your sample, but I've examined my own code and this looks very much like what the compiler would actually generate.






                  share|improve this answer






























                    9














                    Behind the scenes, the compiler is generating a class that represents the closure for your method call. It uses that single instance of the closure class for each iteration of the loop. The code looks something like this, which makes it easier to see why the bug happens:



                    void Main()
                    {
                    List<Func<int>> actions = new List<Func<int>>();

                    int variable = 0;

                    var closure = new CompilerGeneratedClosure();

                    Func<int> anonymousMethodAction = null;

                    while (closure.variable < 5)
                    {
                    if(anonymousMethodAction == null)
                    anonymousMethodAction = new Func<int>(closure.YourAnonymousMethod);

                    //we're re-adding the same function
                    actions.Add(anonymousMethodAction);

                    ++closure.variable;
                    }

                    foreach (var act in actions)
                    {
                    Console.WriteLine(act.Invoke());
                    }
                    }

                    class CompilerGeneratedClosure
                    {
                    public int variable;

                    public int YourAnonymousMethod()
                    {
                    return this.variable * 2;
                    }
                    }


                    This isn't actually the compiled code from your sample, but I've examined my own code and this looks very much like what the compiler would actually generate.






                    share|improve this answer




























                      9












                      9








                      9







                      Behind the scenes, the compiler is generating a class that represents the closure for your method call. It uses that single instance of the closure class for each iteration of the loop. The code looks something like this, which makes it easier to see why the bug happens:



                      void Main()
                      {
                      List<Func<int>> actions = new List<Func<int>>();

                      int variable = 0;

                      var closure = new CompilerGeneratedClosure();

                      Func<int> anonymousMethodAction = null;

                      while (closure.variable < 5)
                      {
                      if(anonymousMethodAction == null)
                      anonymousMethodAction = new Func<int>(closure.YourAnonymousMethod);

                      //we're re-adding the same function
                      actions.Add(anonymousMethodAction);

                      ++closure.variable;
                      }

                      foreach (var act in actions)
                      {
                      Console.WriteLine(act.Invoke());
                      }
                      }

                      class CompilerGeneratedClosure
                      {
                      public int variable;

                      public int YourAnonymousMethod()
                      {
                      return this.variable * 2;
                      }
                      }


                      This isn't actually the compiled code from your sample, but I've examined my own code and this looks very much like what the compiler would actually generate.






                      share|improve this answer















                      Behind the scenes, the compiler is generating a class that represents the closure for your method call. It uses that single instance of the closure class for each iteration of the loop. The code looks something like this, which makes it easier to see why the bug happens:



                      void Main()
                      {
                      List<Func<int>> actions = new List<Func<int>>();

                      int variable = 0;

                      var closure = new CompilerGeneratedClosure();

                      Func<int> anonymousMethodAction = null;

                      while (closure.variable < 5)
                      {
                      if(anonymousMethodAction == null)
                      anonymousMethodAction = new Func<int>(closure.YourAnonymousMethod);

                      //we're re-adding the same function
                      actions.Add(anonymousMethodAction);

                      ++closure.variable;
                      }

                      foreach (var act in actions)
                      {
                      Console.WriteLine(act.Invoke());
                      }
                      }

                      class CompilerGeneratedClosure
                      {
                      public int variable;

                      public int YourAnonymousMethod()
                      {
                      return this.variable * 2;
                      }
                      }


                      This isn't actually the compiled code from your sample, but I've examined my own code and this looks very much like what the compiler would actually generate.







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited May 5 '16 at 7:13









                      sharptooth

                      122k68417838




                      122k68417838










                      answered Mar 29 '13 at 16:49









                      gerrard00gerrard00

                      771713




                      771713























                          7














                          The way around this is to store the value you need in a proxy variable, and have that variable get captured.



                          I.E.



                          while( variable < 5 )
                          {
                          int copy = variable;
                          actions.Add( () => copy * 2 );
                          ++variable;
                          }





                          share|improve this answer



















                          • 1





                            Yeah, it works. But, why?

                            – Morgan Cheng
                            Nov 7 '08 at 7:34











                          • See the explanation in my edited answer. I'm finding the relevant bit of the spec now.

                            – Jon Skeet
                            Nov 7 '08 at 7:35











                          • Haha jon, I actually just read your article: csharpindepth.com/Articles/Chapter5/Closures.aspx You do good work my friend.

                            – tjlevine
                            Nov 7 '08 at 7:36











                          • @tjlevine: Thanks very much. I'll add a reference to that in my answer. I'd forgotten about it!

                            – Jon Skeet
                            Nov 7 '08 at 7:37











                          • Also, Jon, I'd love to read about your thoughts on the various Java 7 closure proposals. I've seen you mention that you wanted to write one, but I haven't seen it.

                            – tjlevine
                            Nov 7 '08 at 7:42
















                          7














                          The way around this is to store the value you need in a proxy variable, and have that variable get captured.



                          I.E.



                          while( variable < 5 )
                          {
                          int copy = variable;
                          actions.Add( () => copy * 2 );
                          ++variable;
                          }





                          share|improve this answer



















                          • 1





                            Yeah, it works. But, why?

                            – Morgan Cheng
                            Nov 7 '08 at 7:34











                          • See the explanation in my edited answer. I'm finding the relevant bit of the spec now.

                            – Jon Skeet
                            Nov 7 '08 at 7:35











                          • Haha jon, I actually just read your article: csharpindepth.com/Articles/Chapter5/Closures.aspx You do good work my friend.

                            – tjlevine
                            Nov 7 '08 at 7:36











                          • @tjlevine: Thanks very much. I'll add a reference to that in my answer. I'd forgotten about it!

                            – Jon Skeet
                            Nov 7 '08 at 7:37











                          • Also, Jon, I'd love to read about your thoughts on the various Java 7 closure proposals. I've seen you mention that you wanted to write one, but I haven't seen it.

                            – tjlevine
                            Nov 7 '08 at 7:42














                          7












                          7








                          7







                          The way around this is to store the value you need in a proxy variable, and have that variable get captured.



                          I.E.



                          while( variable < 5 )
                          {
                          int copy = variable;
                          actions.Add( () => copy * 2 );
                          ++variable;
                          }





                          share|improve this answer













                          The way around this is to store the value you need in a proxy variable, and have that variable get captured.



                          I.E.



                          while( variable < 5 )
                          {
                          int copy = variable;
                          actions.Add( () => copy * 2 );
                          ++variable;
                          }






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 7 '08 at 7:33









                          tjlevinetjlevine

                          32826




                          32826








                          • 1





                            Yeah, it works. But, why?

                            – Morgan Cheng
                            Nov 7 '08 at 7:34











                          • See the explanation in my edited answer. I'm finding the relevant bit of the spec now.

                            – Jon Skeet
                            Nov 7 '08 at 7:35











                          • Haha jon, I actually just read your article: csharpindepth.com/Articles/Chapter5/Closures.aspx You do good work my friend.

                            – tjlevine
                            Nov 7 '08 at 7:36











                          • @tjlevine: Thanks very much. I'll add a reference to that in my answer. I'd forgotten about it!

                            – Jon Skeet
                            Nov 7 '08 at 7:37











                          • Also, Jon, I'd love to read about your thoughts on the various Java 7 closure proposals. I've seen you mention that you wanted to write one, but I haven't seen it.

                            – tjlevine
                            Nov 7 '08 at 7:42














                          • 1





                            Yeah, it works. But, why?

                            – Morgan Cheng
                            Nov 7 '08 at 7:34











                          • See the explanation in my edited answer. I'm finding the relevant bit of the spec now.

                            – Jon Skeet
                            Nov 7 '08 at 7:35











                          • Haha jon, I actually just read your article: csharpindepth.com/Articles/Chapter5/Closures.aspx You do good work my friend.

                            – tjlevine
                            Nov 7 '08 at 7:36











                          • @tjlevine: Thanks very much. I'll add a reference to that in my answer. I'd forgotten about it!

                            – Jon Skeet
                            Nov 7 '08 at 7:37











                          • Also, Jon, I'd love to read about your thoughts on the various Java 7 closure proposals. I've seen you mention that you wanted to write one, but I haven't seen it.

                            – tjlevine
                            Nov 7 '08 at 7:42








                          1




                          1





                          Yeah, it works. But, why?

                          – Morgan Cheng
                          Nov 7 '08 at 7:34





                          Yeah, it works. But, why?

                          – Morgan Cheng
                          Nov 7 '08 at 7:34













                          See the explanation in my edited answer. I'm finding the relevant bit of the spec now.

                          – Jon Skeet
                          Nov 7 '08 at 7:35





                          See the explanation in my edited answer. I'm finding the relevant bit of the spec now.

                          – Jon Skeet
                          Nov 7 '08 at 7:35













                          Haha jon, I actually just read your article: csharpindepth.com/Articles/Chapter5/Closures.aspx You do good work my friend.

                          – tjlevine
                          Nov 7 '08 at 7:36





                          Haha jon, I actually just read your article: csharpindepth.com/Articles/Chapter5/Closures.aspx You do good work my friend.

                          – tjlevine
                          Nov 7 '08 at 7:36













                          @tjlevine: Thanks very much. I'll add a reference to that in my answer. I'd forgotten about it!

                          – Jon Skeet
                          Nov 7 '08 at 7:37





                          @tjlevine: Thanks very much. I'll add a reference to that in my answer. I'd forgotten about it!

                          – Jon Skeet
                          Nov 7 '08 at 7:37













                          Also, Jon, I'd love to read about your thoughts on the various Java 7 closure proposals. I've seen you mention that you wanted to write one, but I haven't seen it.

                          – tjlevine
                          Nov 7 '08 at 7:42





                          Also, Jon, I'd love to read about your thoughts on the various Java 7 closure proposals. I've seen you mention that you wanted to write one, but I haven't seen it.

                          – tjlevine
                          Nov 7 '08 at 7:42











                          4














                          Yes you need to scope variable within the loop and pass it to the lambda that way:



                          List<Func<int>> actions = new List<Func<int>>();

                          int variable = 0;
                          while (variable < 5)
                          {
                          int variable1 = variable;
                          actions.Add(() => variable1 * 2);
                          ++variable;
                          }

                          foreach (var act in actions)
                          {
                          Console.WriteLine(act.Invoke());
                          }

                          Console.ReadLine();





                          share|improve this answer




























                            4














                            Yes you need to scope variable within the loop and pass it to the lambda that way:



                            List<Func<int>> actions = new List<Func<int>>();

                            int variable = 0;
                            while (variable < 5)
                            {
                            int variable1 = variable;
                            actions.Add(() => variable1 * 2);
                            ++variable;
                            }

                            foreach (var act in actions)
                            {
                            Console.WriteLine(act.Invoke());
                            }

                            Console.ReadLine();





                            share|improve this answer


























                              4












                              4








                              4







                              Yes you need to scope variable within the loop and pass it to the lambda that way:



                              List<Func<int>> actions = new List<Func<int>>();

                              int variable = 0;
                              while (variable < 5)
                              {
                              int variable1 = variable;
                              actions.Add(() => variable1 * 2);
                              ++variable;
                              }

                              foreach (var act in actions)
                              {
                              Console.WriteLine(act.Invoke());
                              }

                              Console.ReadLine();





                              share|improve this answer













                              Yes you need to scope variable within the loop and pass it to the lambda that way:



                              List<Func<int>> actions = new List<Func<int>>();

                              int variable = 0;
                              while (variable < 5)
                              {
                              int variable1 = variable;
                              actions.Add(() => variable1 * 2);
                              ++variable;
                              }

                              foreach (var act in actions)
                              {
                              Console.WriteLine(act.Invoke());
                              }

                              Console.ReadLine();






                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered Nov 7 '08 at 7:32









                              cfedukecfeduke

                              20.3k105563




                              20.3k105563























                                  4














                                  The same situation is happening in multi-threading (C#, .NET 4.0].



                                  See the following code:



                                  Purpose is to print 1,2,3,4,5 in order.



                                  for (int counter = 1; counter <= 5; counter++)
                                  {
                                  new Thread (() => Console.Write (counter)).Start();
                                  }


                                  The output is interesting! (It might be like 21334...)



                                  The only solution is to use local variables.



                                  for (int counter = 1; counter <= 5; counter++)
                                  {
                                  int localVar= counter;
                                  new Thread (() => Console.Write (localVar)).Start();
                                  }





                                  share|improve this answer


























                                  • This does not seem to help me. Still non-deterministic.

                                    – Mladen Mihajlovic
                                    Jan 31 '14 at 11:14
















                                  4














                                  The same situation is happening in multi-threading (C#, .NET 4.0].



                                  See the following code:



                                  Purpose is to print 1,2,3,4,5 in order.



                                  for (int counter = 1; counter <= 5; counter++)
                                  {
                                  new Thread (() => Console.Write (counter)).Start();
                                  }


                                  The output is interesting! (It might be like 21334...)



                                  The only solution is to use local variables.



                                  for (int counter = 1; counter <= 5; counter++)
                                  {
                                  int localVar= counter;
                                  new Thread (() => Console.Write (localVar)).Start();
                                  }





                                  share|improve this answer


























                                  • This does not seem to help me. Still non-deterministic.

                                    – Mladen Mihajlovic
                                    Jan 31 '14 at 11:14














                                  4












                                  4








                                  4







                                  The same situation is happening in multi-threading (C#, .NET 4.0].



                                  See the following code:



                                  Purpose is to print 1,2,3,4,5 in order.



                                  for (int counter = 1; counter <= 5; counter++)
                                  {
                                  new Thread (() => Console.Write (counter)).Start();
                                  }


                                  The output is interesting! (It might be like 21334...)



                                  The only solution is to use local variables.



                                  for (int counter = 1; counter <= 5; counter++)
                                  {
                                  int localVar= counter;
                                  new Thread (() => Console.Write (localVar)).Start();
                                  }





                                  share|improve this answer















                                  The same situation is happening in multi-threading (C#, .NET 4.0].



                                  See the following code:



                                  Purpose is to print 1,2,3,4,5 in order.



                                  for (int counter = 1; counter <= 5; counter++)
                                  {
                                  new Thread (() => Console.Write (counter)).Start();
                                  }


                                  The output is interesting! (It might be like 21334...)



                                  The only solution is to use local variables.



                                  for (int counter = 1; counter <= 5; counter++)
                                  {
                                  int localVar= counter;
                                  new Thread (() => Console.Write (localVar)).Start();
                                  }






                                  share|improve this answer














                                  share|improve this answer



                                  share|improve this answer








                                  edited Jan 17 '14 at 18:45









                                  Peter Mortensen

                                  13.8k1987113




                                  13.8k1987113










                                  answered Jan 28 '11 at 14:00









                                  SunilSunil

                                  2,26542738




                                  2,26542738













                                  • This does not seem to help me. Still non-deterministic.

                                    – Mladen Mihajlovic
                                    Jan 31 '14 at 11:14



















                                  • This does not seem to help me. Still non-deterministic.

                                    – Mladen Mihajlovic
                                    Jan 31 '14 at 11:14

















                                  This does not seem to help me. Still non-deterministic.

                                  – Mladen Mihajlovic
                                  Jan 31 '14 at 11:14





                                  This does not seem to help me. Still non-deterministic.

                                  – Mladen Mihajlovic
                                  Jan 31 '14 at 11:14











                                  3














                                  This has nothing to do with loops.



                                  This behavior is triggered because you use a lambda expression () => variable * 2 where the outer scoped variable not actually defined in the lambda's inner scope.



                                  Lambda expressions (in C#3+, as well as anonymous methods in C#2) still create actual methods. Passing variables to these methods involve some dilemmas (pass by value? pass by reference? C# goes with by reference - but this opens another problem where the reference can outlive the actual variable). What C# does to resolve all these dilemmas is to create a new helper class ("closure") with fields corresponding to the local variables used in the lambda expressions, and methods corresponding to the actual lambda methods. Any changes to variable in your code is actually translated to change in that ClosureClass.variable



                                  So your while loop keeps updating the ClosureClass.variable until it reaches 10, then you for loops executes the actions, which all operate on the same ClosureClass.variable.



                                  To get your expected result, you need to create a separation between the loop variable, and the variable that is being closured. You can do this by introducing another variable, i.e.:



                                  List<Func<int>> actions = new List<Func<int>>();
                                  int variable = 0;
                                  while (variable < 5)
                                  {
                                  var t = variable; // now t will be closured (i.e. replaced by a field in the new class)
                                  actions.Add(() => t * 2);
                                  ++variable; // changing variable won't affect the closured variable t
                                  }
                                  foreach (var act in actions)
                                  {
                                  Console.WriteLine(act.Invoke());
                                  }


                                  You could also move the closure to another method to create this separation:



                                  List<Func<int>> actions = new List<Func<int>>();

                                  int variable = 0;
                                  while (variable < 5)
                                  {
                                  actions.Add(Mult(variable));
                                  ++variable;
                                  }

                                  foreach (var act in actions)
                                  {
                                  Console.WriteLine(act.Invoke());
                                  }


                                  You can implement Mult as a lambda expression (implicit closure)



                                  static Func<int> Mult(int i)
                                  {
                                  return () => i * 2;
                                  }


                                  or with an actual helper class:



                                  public class Helper
                                  {
                                  public int _i;
                                  public Helper(int i)
                                  {
                                  _i = i;
                                  }
                                  public int Method()
                                  {
                                  return _i * 2;
                                  }
                                  }

                                  static Func<int> Mult(int i)
                                  {
                                  Helper help = new Helper(i);
                                  return help.Method;
                                  }


                                  In any case, "Closures" are NOT a concept related to loops, but rather to anonymous methods / lambda expressions use of local scoped variables - although some incautious use of loops demonstrate closures traps.






                                  share|improve this answer






























                                    3














                                    This has nothing to do with loops.



                                    This behavior is triggered because you use a lambda expression () => variable * 2 where the outer scoped variable not actually defined in the lambda's inner scope.



                                    Lambda expressions (in C#3+, as well as anonymous methods in C#2) still create actual methods. Passing variables to these methods involve some dilemmas (pass by value? pass by reference? C# goes with by reference - but this opens another problem where the reference can outlive the actual variable). What C# does to resolve all these dilemmas is to create a new helper class ("closure") with fields corresponding to the local variables used in the lambda expressions, and methods corresponding to the actual lambda methods. Any changes to variable in your code is actually translated to change in that ClosureClass.variable



                                    So your while loop keeps updating the ClosureClass.variable until it reaches 10, then you for loops executes the actions, which all operate on the same ClosureClass.variable.



                                    To get your expected result, you need to create a separation between the loop variable, and the variable that is being closured. You can do this by introducing another variable, i.e.:



                                    List<Func<int>> actions = new List<Func<int>>();
                                    int variable = 0;
                                    while (variable < 5)
                                    {
                                    var t = variable; // now t will be closured (i.e. replaced by a field in the new class)
                                    actions.Add(() => t * 2);
                                    ++variable; // changing variable won't affect the closured variable t
                                    }
                                    foreach (var act in actions)
                                    {
                                    Console.WriteLine(act.Invoke());
                                    }


                                    You could also move the closure to another method to create this separation:



                                    List<Func<int>> actions = new List<Func<int>>();

                                    int variable = 0;
                                    while (variable < 5)
                                    {
                                    actions.Add(Mult(variable));
                                    ++variable;
                                    }

                                    foreach (var act in actions)
                                    {
                                    Console.WriteLine(act.Invoke());
                                    }


                                    You can implement Mult as a lambda expression (implicit closure)



                                    static Func<int> Mult(int i)
                                    {
                                    return () => i * 2;
                                    }


                                    or with an actual helper class:



                                    public class Helper
                                    {
                                    public int _i;
                                    public Helper(int i)
                                    {
                                    _i = i;
                                    }
                                    public int Method()
                                    {
                                    return _i * 2;
                                    }
                                    }

                                    static Func<int> Mult(int i)
                                    {
                                    Helper help = new Helper(i);
                                    return help.Method;
                                    }


                                    In any case, "Closures" are NOT a concept related to loops, but rather to anonymous methods / lambda expressions use of local scoped variables - although some incautious use of loops demonstrate closures traps.






                                    share|improve this answer




























                                      3












                                      3








                                      3







                                      This has nothing to do with loops.



                                      This behavior is triggered because you use a lambda expression () => variable * 2 where the outer scoped variable not actually defined in the lambda's inner scope.



                                      Lambda expressions (in C#3+, as well as anonymous methods in C#2) still create actual methods. Passing variables to these methods involve some dilemmas (pass by value? pass by reference? C# goes with by reference - but this opens another problem where the reference can outlive the actual variable). What C# does to resolve all these dilemmas is to create a new helper class ("closure") with fields corresponding to the local variables used in the lambda expressions, and methods corresponding to the actual lambda methods. Any changes to variable in your code is actually translated to change in that ClosureClass.variable



                                      So your while loop keeps updating the ClosureClass.variable until it reaches 10, then you for loops executes the actions, which all operate on the same ClosureClass.variable.



                                      To get your expected result, you need to create a separation between the loop variable, and the variable that is being closured. You can do this by introducing another variable, i.e.:



                                      List<Func<int>> actions = new List<Func<int>>();
                                      int variable = 0;
                                      while (variable < 5)
                                      {
                                      var t = variable; // now t will be closured (i.e. replaced by a field in the new class)
                                      actions.Add(() => t * 2);
                                      ++variable; // changing variable won't affect the closured variable t
                                      }
                                      foreach (var act in actions)
                                      {
                                      Console.WriteLine(act.Invoke());
                                      }


                                      You could also move the closure to another method to create this separation:



                                      List<Func<int>> actions = new List<Func<int>>();

                                      int variable = 0;
                                      while (variable < 5)
                                      {
                                      actions.Add(Mult(variable));
                                      ++variable;
                                      }

                                      foreach (var act in actions)
                                      {
                                      Console.WriteLine(act.Invoke());
                                      }


                                      You can implement Mult as a lambda expression (implicit closure)



                                      static Func<int> Mult(int i)
                                      {
                                      return () => i * 2;
                                      }


                                      or with an actual helper class:



                                      public class Helper
                                      {
                                      public int _i;
                                      public Helper(int i)
                                      {
                                      _i = i;
                                      }
                                      public int Method()
                                      {
                                      return _i * 2;
                                      }
                                      }

                                      static Func<int> Mult(int i)
                                      {
                                      Helper help = new Helper(i);
                                      return help.Method;
                                      }


                                      In any case, "Closures" are NOT a concept related to loops, but rather to anonymous methods / lambda expressions use of local scoped variables - although some incautious use of loops demonstrate closures traps.






                                      share|improve this answer















                                      This has nothing to do with loops.



                                      This behavior is triggered because you use a lambda expression () => variable * 2 where the outer scoped variable not actually defined in the lambda's inner scope.



                                      Lambda expressions (in C#3+, as well as anonymous methods in C#2) still create actual methods. Passing variables to these methods involve some dilemmas (pass by value? pass by reference? C# goes with by reference - but this opens another problem where the reference can outlive the actual variable). What C# does to resolve all these dilemmas is to create a new helper class ("closure") with fields corresponding to the local variables used in the lambda expressions, and methods corresponding to the actual lambda methods. Any changes to variable in your code is actually translated to change in that ClosureClass.variable



                                      So your while loop keeps updating the ClosureClass.variable until it reaches 10, then you for loops executes the actions, which all operate on the same ClosureClass.variable.



                                      To get your expected result, you need to create a separation between the loop variable, and the variable that is being closured. You can do this by introducing another variable, i.e.:



                                      List<Func<int>> actions = new List<Func<int>>();
                                      int variable = 0;
                                      while (variable < 5)
                                      {
                                      var t = variable; // now t will be closured (i.e. replaced by a field in the new class)
                                      actions.Add(() => t * 2);
                                      ++variable; // changing variable won't affect the closured variable t
                                      }
                                      foreach (var act in actions)
                                      {
                                      Console.WriteLine(act.Invoke());
                                      }


                                      You could also move the closure to another method to create this separation:



                                      List<Func<int>> actions = new List<Func<int>>();

                                      int variable = 0;
                                      while (variable < 5)
                                      {
                                      actions.Add(Mult(variable));
                                      ++variable;
                                      }

                                      foreach (var act in actions)
                                      {
                                      Console.WriteLine(act.Invoke());
                                      }


                                      You can implement Mult as a lambda expression (implicit closure)



                                      static Func<int> Mult(int i)
                                      {
                                      return () => i * 2;
                                      }


                                      or with an actual helper class:



                                      public class Helper
                                      {
                                      public int _i;
                                      public Helper(int i)
                                      {
                                      _i = i;
                                      }
                                      public int Method()
                                      {
                                      return _i * 2;
                                      }
                                      }

                                      static Func<int> Mult(int i)
                                      {
                                      Helper help = new Helper(i);
                                      return help.Method;
                                      }


                                      In any case, "Closures" are NOT a concept related to loops, but rather to anonymous methods / lambda expressions use of local scoped variables - although some incautious use of loops demonstrate closures traps.







                                      share|improve this answer














                                      share|improve this answer



                                      share|improve this answer








                                      edited Jun 14 '18 at 8:53

























                                      answered Jun 13 '18 at 12:21









                                      David RefaeliDavid Refaeli

                                      9021828




                                      9021828























                                          0














                                          It is called the closure problem,
                                          simply use a copy variable, and it's done.



                                          List<Func<int>> actions = new List<Func<int>>();

                                          int variable = 0;
                                          while (variable < 5)
                                          {
                                          int i = variable;
                                          actions.Add(() => i * 2);
                                          ++ variable;
                                          }

                                          foreach (var act in actions)
                                          {
                                          Console.WriteLine(act.Invoke());
                                          }





                                          share|improve this answer



















                                          • 1





                                            In what way your answer is different from the answer provided by someone above?

                                            – Thangadurai
                                            Jan 30 at 7:38
















                                          0














                                          It is called the closure problem,
                                          simply use a copy variable, and it's done.



                                          List<Func<int>> actions = new List<Func<int>>();

                                          int variable = 0;
                                          while (variable < 5)
                                          {
                                          int i = variable;
                                          actions.Add(() => i * 2);
                                          ++ variable;
                                          }

                                          foreach (var act in actions)
                                          {
                                          Console.WriteLine(act.Invoke());
                                          }





                                          share|improve this answer



















                                          • 1





                                            In what way your answer is different from the answer provided by someone above?

                                            – Thangadurai
                                            Jan 30 at 7:38














                                          0












                                          0








                                          0







                                          It is called the closure problem,
                                          simply use a copy variable, and it's done.



                                          List<Func<int>> actions = new List<Func<int>>();

                                          int variable = 0;
                                          while (variable < 5)
                                          {
                                          int i = variable;
                                          actions.Add(() => i * 2);
                                          ++ variable;
                                          }

                                          foreach (var act in actions)
                                          {
                                          Console.WriteLine(act.Invoke());
                                          }





                                          share|improve this answer













                                          It is called the closure problem,
                                          simply use a copy variable, and it's done.



                                          List<Func<int>> actions = new List<Func<int>>();

                                          int variable = 0;
                                          while (variable < 5)
                                          {
                                          int i = variable;
                                          actions.Add(() => i * 2);
                                          ++ variable;
                                          }

                                          foreach (var act in actions)
                                          {
                                          Console.WriteLine(act.Invoke());
                                          }






                                          share|improve this answer












                                          share|improve this answer



                                          share|improve this answer










                                          answered Dec 12 '18 at 13:52









                                          Juned Khan MominJuned Khan Momin

                                          546




                                          546








                                          • 1





                                            In what way your answer is different from the answer provided by someone above?

                                            – Thangadurai
                                            Jan 30 at 7:38














                                          • 1





                                            In what way your answer is different from the answer provided by someone above?

                                            – Thangadurai
                                            Jan 30 at 7:38








                                          1




                                          1





                                          In what way your answer is different from the answer provided by someone above?

                                          – Thangadurai
                                          Jan 30 at 7:38





                                          In what way your answer is different from the answer provided by someone above?

                                          – Thangadurai
                                          Jan 30 at 7:38





                                          protected by Elenasys Jan 6 '14 at 22:10



                                          Thank you for your interest in this question.
                                          Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                                          Would you like to answer one of these unanswered questions instead?



                                          Popular posts from this blog

                                          Monofisismo

                                          Angular Downloading a file using contenturl with Basic Authentication

                                          Olmecas