在闭包中访问变量

时间:2014-11-10 09:15:19

标签: c# closures resharper predicate

我知道在SO上有很多关于这个问题的话题,Eric Lippert还有一篇很棒的帖子。我仍然不太确定以下代码中发生了什么以及Resharper警告的原因:

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
    }
  }
}

这可以通过以下方式轻松解决:

var localCopy = item;
if (list2.Exists(o => o.Id == localCopy.Id))

据我所知,所有在exists中创建的闭包确实引用了同一个实例,如果是localCopy,对吗?但这不应该是一个问题,因为存在是立即评估的吗?那我在哪里错了?

1 个答案:

答案 0 :(得分:4)

  

但这不应该是一个问题,因为存在会立即评估吗?

是的,GenericClass.Exists急切地评估lambda,但ReSharper并不知道。

所有ReSharper都知道你将一个闭包传递给另一个方法 - 该方法可能懒惰地执行lambda,因此警告。


  

有没有办法告诉resharper,对于那种方法,不需要警告?

查看文档,似乎可以使用InstantHandleAttribute属性修饰谓词参数。

  

告诉代码分析引擎,如果在调用的方法处于堆栈时完全处理参数。如果参数是委托,则表示在执行方法时执行委托。如果参数是可枚举的,则表示在执行方法时枚举它

请参阅此处了解如何安装JetBrains代码注释属性:Annotations in Source Code