Объем объектов в лямбда-выражениях - PullRequest
2 голосов
/ 16 декабря 2011

Я новичок в C # и пытаюсь понять лямбда-выражения вместе с делегатами. Это код, который я использую:

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();
        }
    }
}

Что я не понимаю, так это вызов d2 print true. Когда было построено d2, значение j было 0. Он был изменен только после того, как d1 был вызван позже в testMethod. Так как это печать True? что мне здесь не хватает?

Ответы [ 2 ]

6 голосов
/ 16 декабря 2011

d1 и d2 оба ссылаются на один и тот же экземпляр j.Когда вы устанавливаете j, вызывая d1, вы также изменяете значение переменной, которую может видеть d2.

Если вы хотите, чтобы у них был другой экземпляр j, вам понадобитсядля области видимости переменной:

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

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

Однако, если вы собираетесь это сделать, вы можете использовать две разные переменные, скажем, j1 и j2.Это будет более читабельным.

3 голосов
/ 16 декабря 2011

Когда вы создаете делегата, любая переменная вне его области действия захватывается.В этом случае делегаты, назначенные d1 и d2, захватывают переменную j, объявленную внутри testMethod();они не создают копии j, они фиксируют фактическую переменную.В этом смысле, в течение времени жизни d1 и d2, j ведет себя внутри них, как если бы это была глобальная переменная (хотя, конечно, в C # такой вещи нет как глобальной переменной).

Если вы хотите, чтобы эти методы получали отдельные экземпляры j, вам нужно будет предоставить каждому методу копию j вместо того, чтобы просто использовать ее.Например:

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);

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...