Integer handled as reference type when passed into a delegate

后端 未结 4 1297
面向向阳花
面向向阳花 2020-12-21 05:25

I was attending the TechDays 2013 in the Netherlands this week and I got an interesting quiz question presented. The question was: What is the output of the following progra

4条回答
  •  感情败类
    2020-12-21 06:02

    It is because it is a captured variable. Note that this used to also happen with foreach, but that changed in C# 5. But to re-write your code to what you actually have:

    class Program
    {
        delegate void Writer();
    
        class CaptureContext { // generated by the compiler and named something
            public int i;      // truly horrible that is illegal in C#
            public void DoStuff() {
                Console.WriteLine(i);
            }
        }
        static void Main(string[] args)
        {
            var writers = new List();
            var ctx = new CaptureContext();
            for (ctx.i = 0; ctx.i < 10; ctx.i++)
            {
                writers.Add(ctx.DoStuff);
            }
    
            foreach (Writer writer in writers)
            {
                writer();
            }
        }
    }
    

    As you can see: there is only one ctx thus only one ctx.i, and it is 10 by the time you foreach over writers.

    Btw, if you want to make the old code work:

    for (int tmp = 0; tmp < 10; tmp++)
    {
        int i = tmp;
        writers.Add(delegate { Console.WriteLine(i); });
    }
    

    Basically, the capture-context is scoped at the same level as the variable; here the variable is scoped inside the loop, so this generates:

    for (int tmp = 0; tmp < 10; tmp++)
    {
        var ctx = new CaptureContext();
        ctx.i = tmp;
        writers.Add(ctx.DoStuff);
    }
    

    Here each DoStuff is on a different capture-context instance, so has a different and separate i.

提交回复
热议问题