代码之家  ›  专栏  ›  技术社区  ›  James King

访问修改后的闭包…但为什么?

  •  5
  • James King  · 技术社区  · 15 年前

    在这里看到了几个类似的问题,但似乎没有一个是我的问题。。。

    因为 primaryApps 在for循环的上下文中声明, primary 在我处理的时候不会改变的 . 如果我宣布 当然,在for循环之外,我还有闭包问题。但为什么在下面的代码中?

    var primaries = (from row in openRequestsDataSet.AppPrimaries
                     select row.User).Distinct();
    
        foreach (string primary in primaries) {
    
            // Complains because 'primary' is accessing a modified closure
            var primaryApps = openRequestsDataSet.AppPrimaries.Select(x => x.User == primary);
    

    是因为Resharper不够聪明,不能弄清楚这不是一个问题,还是有一个原因,就是闭包是一个我没有看到的问题?

    4 回复  |  直到 15 年前
        1
  •  10
  •   JaredPar    15 年前

    问题在下面的语句中

    因为primaryApps是在for循环的上下文中声明的,所以当我处理primaryApps时,primary不会改变。

    Resharper根本没有办法100%验证这一点。在此引用闭包的lambda被传递给此循环上下文之外的函数: AppPrimaries.Select 方法。此函数本身可以存储生成的委托表达式,稍后执行它并直接运行到捕获迭代变量问题。

        2
  •  8
  •   Eric Lippert    15 年前

    因为primaryApps是在for循环的上下文中声明的,所以当我处理primaryApps时,primary不会改变。如果我在for循环之外声明了primaryApps,那么绝对会有闭包问题。但为什么在下面的代码中?

    仍然存在捕获的循环变量问题。很容易做到。

    static class Extensions
    {
        public IEnumerable<int> Select(this IEnumerable<int> items, Func<int, bool> selector)
        {
            C.list.Add(selector);
            return System.Enumerable.Select(items, selector);
        }
    }
    
    class C
    {
        public static List<Func<int, bool>> list = new List<Func<int, bool>>();
        public static void M()
        { 
            int[] primaries = { 10, 20, 30}; 
            int[] secondaries = { 11, 21, 30}; 
    
            foreach (int primary in primaries) 
            {
                var primaryApps = secondaries.Select(x => x == primary);
                // do something with primaryApps
            }
            C.N();
        }
        public static void N()
        {
            Console.WriteLine(C.list[0](10)); // true or false?
        }
    }
    

    “primaryApps”的声明是 完全无关 关闭可能会在循环中存活下来 ,因此 以后可能会有人调用它

    Resharper无法知道Select的一个特定实现并没有为以后隐藏选择器;事实上,这正是所有这些实现 . 雷沙普怎么会知道他们碰巧把它藏在一个稍后无法接近的地方?

        3
  •  1
  •   Giorgi    15 年前

    据我所知,Resharper在每次访问foreach变量时都会生成警告,即使它不会真正导致闭包。

        4
  •  0
  •   Cihan Yakar    15 年前