开发者

Multiple closures and ReSharper's "Access to Modified Closure" Warning

开发者 https://www.devze.com 2023-03-24 01:55 出处:网络
I\'ve got code like the following: private void SetupCheeseShop(Button buyCheese, Button spoilCheese) {

I've got code like the following:

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

    spoilCheese.Click += (sender, e) => {
        // "Access to Modified Closure" warning开发者_StackOverflow社区 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 is warning me that I'm accessing a modified closure when reading from cheeseCount in the spoil-cheese handler. Can I safely ignore it in this case?

I'm expecting the cheese count to be modified between calls to the first closure, but I'm not sure what happens when the code doing the modifying is in a second closure around the same variable.


You can safely ignore the warning in your case. It warns you that the closed over variable can potentially have a different value than the current value (0) at the time the closure is created. That's what you want here. You can have any number of closures, they all reference the same variable. Think of a closure variable as a field in a class (which is what the compiler generates).

As stated in section §5.1.7 of the C# Language Specification 4.0:

If the local variable is captured by an anonymous function (§7.15.5.1), its lifetime extends at least until the delegate or expression tree created from the anonymous function, along with any other objects that come to reference the captured variable, are eligible for garbage collection.

You can safely rely on this behavior: the variable stays the same, no matter how many anonymous functions are referencing it, until the event handlers are collected, which won't happen until the buttons themselves are collected in your example.


Your cheeseCount variable is not a field, and scope of your variable is only within your own method.

You should move your cheeseCount out of your method and make it a field.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号