Reputation: 3175
I know there has been a lot topics about that issue on SO and there is also a great post from Eric Lippert. Still I'm not quite sure what is happening in the following code and the reason for the Resharper warning:
public class Class
{
public string Id { get; set; }
}
public class GenericClass<T>
{
public virtual bool Exists(Predicate<T> match)
{
return true;
}
}
public class Main
{
public void Test()
{
var list = new List<Class>();
var list2 = new GenericClass<Class>();
foreach (var item in list)
{
if (list2.Exists(o => o.Id == item.Id)) // access to variable in closure on item
}
}
}
This can be easily fixed by this:
var localCopy = item;
if (list2.Exists(o => o.Id == localCopy.Id))
As far as I understand all closures which are created in the exists does reference the same instance if localCopy, correct? But this should not be an issue since the exists is evaluated instantly right? So where am I wrong here?
Upvotes: 1
Views: 82
Reputation: 68750
But this should not be an issue since the exists is evaluated instantly right?
Yes, GenericClass.Exists
evaluates the lambda eagerly, but ReSharper doesn't know that.
All ReSharper knows is that you're passing a closure to another method - that method might execute the lambda lazily, hence the warning.
Is there any way to tell resharper that, for that method, there is no need for the warning?
Looking at the documentation, it seems you could decorate the predicate parameter with the InstantHandleAttribute
attribute.
Tells code analysis engine if the parameter is completely handled when the invoked method is on stack. If the parameter is a delegate, indicates that delegate is executed while the method is executed. If the parameter is an enumerable, indicates that it is enumerated while the method is executed
See here for how to install JetBrains code annotation attributes: Annotations in Source Code
Upvotes: 4