开发者

Do.. While.. with Exists predicates. Access to modified closure?

string reference;
do {
  reference = GenerateNewReference();
} while (currentItems.Ex开发者_高级运维ists(i=>i.Reference.Equals(reference));

ReSharper is warning me about this, something called Access to Modified Closure. I've tried my best to read and understand it, but my code still seems fine to me.

Is there a problem with my code?


It's fine in your case because the value of reference doesn't change over the lifetime of your lambda. But resharper doesn't know that. As far as resharper can see the lambda might survive for a longer time during which reference changes its value.

The rule is intended to warn you when you write code like this:

int myInt=1;
Func<int,bool> IsOne = i=>i==myInt;
myInt=2;
IsOne(1);//=> false
IsOne(2);//=> true

because the IsOne lambda binds to myInt by reference, and not by value.


No, there's no problem because the List<T>.Exists method executes eagerly. Consequently, changes in the value of the captured variable are "responded to" immediately. You do have a modified-closure, but that isn't necessarily (as in this case) wrong.

On the other hand, if you'd added the "lambda" (really the delegate) to a list inside the loop and then run these queries afterwards, you'd run in to the actual modified-closure problems that Resharper is warning you about.

If want to get rid of the warning, you could do:

string reference;
do {
  reference = GenerateNewReference();
  var refCopy = reference;
} while (currentItems.Exists(i => i.Reference.Equals(refCopy));

Slightly off-topic: If you want a fancy of way of writing your search (without any modified-closure warnings), you could write a utility method such as:

public static IEnumerable<T> Generate(Func<T> func)
{ 
     if(func == null)
        throw new ArgumentNullException("func");

     while(true)
        yield return func();
}

And then use it as:

var result = MyExtensions.Generate(GenerateNewReference)
                         .First(reference => !currentItems.Exists(i => i.Reference.Equals(reference)));
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜