Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scope of objects in lambda expressions

I am new to C# and trying to understand lambda expressions along with delegates. This is the code I am running:

delegate bool D1();
delegate bool D2(int i);

namespace Console
{
    class Program
    {
        D1 d1;
        D2 d2;

        public void testMethod(int input)
        {
            int j = 0;
            d1 = () => { j = 10; return j < input; };
            d2 = (x) => { return x == j; };
            System.Console.WriteLine("j = {0}", j);

            bool res = d1();
            System.Console.WriteLine("res={0}, j ={1}", res, j);

        }

        static void Main(string[] args)
        {
            Program p = new Program();
            p.testMethod(10);
            System.Console.WriteLine(p.d2(10));
            System.Console.ReadKey();
        }
    }
}

What I don't understand is the invocation of d2 prints true. When d2 was constructed value of j was 0. It was changed only after d1 was invoked later in the testMethod. So how it is printing True ? what am I missing here?

like image 555
Naveen Avatar asked Feb 15 '26 06:02

Naveen


2 Answers

d1 and d2 both refer to the same instance of j. When you set j by calling d1 you're also altering the value of the variable that d2 can see.

If you want them do have different instance of j you'll need to scope the variable:

{
  int j = 0;
  d1 = () => { j = 10; return j < input; };
}

{
  int j = 0;
  d2 = (x) => { return x == j; };
}

However, if you're going to do this then you might as well have two different variables, say j1 and j2 instead. This will be more readable.

like image 179
Sean Avatar answered Feb 17 '26 19:02

Sean


When you create a delegate, any variable outside its scope that it uses is captured. In this case, the delegates assigned to d1 and d2 both capture the variable j declared inside testMethod(); they don't create copies of j, they capture the actual variable. In this sense, during the lifetime of d1 and d2, j behaves inside them as if it was a global variable (though there is no such thing as a global variable in C#, of course).

If you want those methods to get separate instances of j, you would need to provide each method with a copy of j instead of just using it. For instance:

public void testMethod(int input)
{
    int j = 0;
    int k = j;
    d1 = () => { j = 10; return j < input; };
    d2 = (x) => { return x == k; };
    System.Console.WriteLine("j = {0}", j);

    bool res = d1();
    System.Console.WriteLine("res={0}, j ={1}", res, j);

}
like image 40
Gorpik Avatar answered Feb 17 '26 19:02

Gorpik



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!