4
class Program
    {        
        static Action act = null;

        static void Main(string[] args)
        {
            Test();
            act();
            act();
            Test();
            act();
        }   

        static void Test()
        {
            int count = 0;

            if(act == null) act = () => Console.Write(++count + " ");
        }
    }  

result : 1 2 3 why?

if delete [ if(act == null) ] result : 1 2 1

1
  • 1
    Lambda captures outter context. This way even if function leaves it's scope and disposes you will be able to use it inside and not receive NRE. Your counter is captured by reference in your lambda. Commented Sep 23, 2019 at 6:43

3 Answers 3

11

Currently, you're only creating a single delegate instance. That captures the local variable that was declared in the Test method the first time it was called.

That local variable effectively has an extended lifetime due to the delegate that captures it. Every time you invoke the delegate, it increments the same variable.

When you remove the if (act == null) condition, you create a new delegate each time you call Test, which means it captures a different count local variable, starting at 0 each time. You're calling Test() twice, and the delegate created through the first call is invoked twice (with output 1 then 2). The delegate create through the second call is only invoked once (with output 1).

Sign up to request clarification or add additional context in comments.

Comments

3

When you call this code:

act = () => Console.Write(++count + " ");

You capture the local variable count within the action. Each subsequent call to act() uses this captured variable. So if it starts as 0, it becomes 1, 2, and then 3.

So with the if(act == null) part, you will only ever assign act a single time, so the second call to Test() doesn't reassign act and doesn't capture the new count variable. Therefore, it keeps using the original one, meaning it increments to 3.

Without the if statement, you capture the new count variable each time you call Test(), so it effectively resets to 0.

This is a related question.

Comments

1

Without testing if act is null, when you call Test() for the second time, it assigns a new inline function to act.

Each inline act() have access to a different count version in the heap memory.

To understand, think that the compiler "reminds" that each act has access to the last call to Test memory space.

Each time Test is called, it creates a distinct heap space, so count has different value.

If you test if act is null and not create a new act inline function, act use only one count.

If you create a new act because of not testing if null, each act has access to a new count version like if it was a new instance of an object having count as member.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.