Многочисленные замыкания и предупреждение ReSharper «Доступ к измененному замыканию» - PullRequest
3 голосов
/ 29 июля 2011

У меня есть код, подобный следующему:

private void SetupCheeseShop(Button buyCheese, Button spoilCheese)
{
    var cheeseCount = 0;    // No cheese

    spoilCheese.Click += (sender, e) => {
        // "Access to Modified Closure" warning occurs for cheeseCount below:
        MessageBox.Show(string.Format("{0} cheeses have spoiled", cheeseCount));

        cheeseCount = 0;    // Throw out moldy cheese
    };


    buyCheese.Click += (sender, e) => {
        cheeseCount++;
    };
}

ReSharper предупреждает меня, что я получаю доступ к измененному закрытию при чтении из cheeseCount в обработчике спойл-сыра.Могу ли я безопасно проигнорировать это в этом случае?

Я ожидаю, что счетчик сыра будет изменен между вызовами первого закрытия, но я не уверен, что происходит, когда код, выполняющий изменение, находится во второмзамыкание вокруг той же переменной.

Ответы [ 2 ]

2 голосов
/ 29 июля 2011

Вы можете смело игнорировать предупреждение в вашем случае.Он предупреждает вас, что закрытая переменная может потенциально иметь значение, отличное от текущего значения (0) во время создания замыкания.Это то, что вы хотите здесь.Вы можете иметь любое количество замыканий, все они ссылаются на одну и ту же переменную.Подумайте о переменной замыкания как о поле в классе (которое генерирует компилятор).

Как указано в разделе §5.1.7 спецификации языка C # 4.0 :

Если локальная переменная захвачена анонимной функцией (§7.15.5.1), ее время жизни увеличивается, по крайней мере, до дерева делегатов или выражений, созданного из анонимной функции, вместе с любыми другими объектами, которые приходят для ссылки назахваченная переменная, пригодна для сбора мусора.

Вы можете смело полагаться на это поведение: переменная остается неизменной, независимо от того, сколько анонимных функций ссылается на нее, до тех пор, пока не будут собраны обработчики событий, которыене произойдет, пока сами кнопки не будут собраны в вашем примере.

0 голосов
/ 29 июля 2011

Ваша переменная cheeseCount не является полем, а область действия вашей переменной - только в пределах вашего собственного метода.

Вы должны убрать свой cheeseCount из вашего метода и сделать его полем.

...