繁体   English   中英

可以访问修改后的闭包...但是为什么呢?

[英]Access to modified closure… but why?

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

我了解(或以为我了解)闭包的概念,并且了解什么会导致Resharper抱怨访问已修改的闭包,但是在下面的代码中,我不明白我是如何违反闭包的。

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

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是否只是不够聪明,以至于没有发现这是一个问题,还是有一个我没有看到的关闭问题的原因?

问题在以下语句中

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

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

正确地检测这是否可能是一项艰巨的任务,坦率地说,这是不值得的。 取而代之的是,ReSharper采取了安全路线,并警告您可能会危险地捕获迭代变量。

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

贾里德是对的; 说明为什么你的结论不是从你的前提逻辑可循,让我们的上下文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的特定实现不会隐藏选择器以供以后使用。 实际上,这正是他们所有人所做的 Resharper应该如何得知他们碰巧将其藏在一个以后无法访问的地方?

据我所知,Resharper每次访问foreach变量都会生成警告,即使它并没有真正导致关闭。

是的,这只是警告,请看: http : //devnet.jetbrains.net/thread/273042

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM