Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# object references and Action types [duplicate]

I have a quick question hopefully about Action types and Lambdas in C#. Here's come code:

    static void Main(string[] args)
    {
        List<Action> actions = new List<Action>();

        for (int I = 0; I < 10; I++)
            actions.Add(new Action(() => Print(I.ToString())));

        foreach (Action a in actions)
        {
            a.Invoke();
        }
        actions.Clear();

        int X;
        for (X = 0; X < 10; X++)
        {
            int V = X;
            actions.Add(new Action(() => Print(V.ToString())));
        }

        foreach (Action a in actions)
        {
            a.Invoke();
        }
        Console.ReadLine();
    }


    public static void Print(string s)
    {
        Console.WriteLine(s);
    }

If you run this code you will see that it outputs 10, ten times in a row, then outputs the numbers 0-9 the second time around. It clearly has something to do with the way I use X vs I, and how I give my action a new variable V each time in the second loop... Possibly that each new V is a new address in memory, but I'm struggling to understand why I.ToString() doesn't do the same thing in the first loop... Why doesn't I.ToString() used in the first Action work in the same way as the second example?

like image 956
Mark W Avatar asked Feb 16 '16 17:02

Mark W


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

Is C language easy?

Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.

What is C in C language?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.


1 Answers

The for loop is effectively expanded out to this by the compiler:

{
  int I;
  for (I = 0; I < 10; I++)
  {
    actions.Add(new Action(() => Print(I.ToString())));
  }
}

This means that all the lambda instances capture the same instance of I, which will be 10 when the loop exits.

In your second example you copy the value into a variable that is scoped to the body of the for statement, and the lambda captures this local. There will be a unique local for each repetition of the loop.

It's important to realize that you don't capture the value of the variable, rather you capture the variable itself. That's why the first example doesn't work, but the second one does.

like image 83
Sean Avatar answered Sep 29 '22 01:09

Sean