Search code examples
c#lambdaresharperpredicate

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


string reference;
do {
  reference = GenerateNewReference();
} while (currentItems.Exists(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?


Solution

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