简体   繁体   English

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

[英]Access to modified closure… but why?

Saw several similar questions here, but none of them seemed to quite be my issue... 在这里看到了几个类似的问题,但似乎没有一个问题完全是我的问题。

I understand (or thought I understood) the concept of closure, and understand what would cause Resharper to complain about access to a modified closure, but in the below code I don't understand how I'm breaching closure. 我了解(或以为我了解)闭包的概念,并且了解什么会导致Resharper抱怨访问已修改的闭包,但是在下面的代码中,我不明白我是如何违反闭包的。

Because primaryApps is declared within the context of the for loop, primary isn't going to change while I'm processing primaryApps . 因为primaryApps是在for循环的上下文中声明的,所以在我处理primaryApps时, primary不会改变。 If I had declared primaryApps outside the for loop, then absolutely, I have closure issues. 如果我在for循环外声明了primaryApps ,那么绝对有关闭问题。 But why in the code below? 但是为什么在下面的代码中呢?

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

Is Resharper just not smart enough to figure out it's not an issue, or is there a reason closure is an issue here that I'm not seeing? Resharper是否只是不够聪明,以至于没有发现这是一个问题,还是有一个我没有看到的关闭问题的原因?

The problem is in the following statement 问题在以下语句中

Because primaryApps is declared within the context of the for loop, primary isn't going to change while I'm processing primaryApps. 因为primaryApps是在for循环的上下文中声明的,所以在我处理primaryApps时,primary不会改变。

There is simply no way for Resharper to 100% verify this. Resharper根本无法100%验证这一点。 The lambda which references the closure here is passed to function outside the context of this loop: The AppPrimaries.Select method. 引用闭包的lambda传递给此循环上下文之外的函数: AppPrimaries.Select方法。 This function could itself store the resulting delegate expression, execute it later and run straight into the capture of the iteration variable issue. 该函数本身可以存储生成的委托表达式,稍后执行它,然后直接运行到捕获迭代变量问题中。

Properly detecting whether or not this is possible is quite an undertaking and frankly not worth the effort. 正确地检测这是否可能是一项艰巨的任务,坦率地说,这是不值得的。 Instead ReSharper is taking the safe route and warning about the potentially dangerous capture of the iteration variable. 取而代之的是,ReSharper采取了安全路线,并警告您可能会危险地捕获迭代变量。

Because primaryApps is declared within the context of the for loop, primary isn't going to change while I'm processing primaryApps. 因为primaryApps是在for循环的上下文中声明的,所以在我处理primaryApps时,primary不会改变。 If I had declared primaryApps outside the for loop, then absolutely, I have closure issues. 如果我在for循环外声明了primaryApps,那么绝对有关闭问题。 But why in the code below? 但是为什么在下面的代码中呢?

Jared is right; 贾里德是对的; to demonstrate why your conclusion does not follow logically from your premise, let's make a program that declares primaryApps within the context for the for loop, and still suffers from a captured loop variable problem. 说明为什么你的结论不是从你的前提逻辑可循,让我们的上下文for循环内声明primaryApps程序, 从捕获的循环变量问题仍然困扰。 Easy enough to do that. 很容易做到这一点。

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

Where "primaryApps" is declared is completely irrelevant . 声明“ primaryApps”的地方是完全不相关的 The only thing that is relevant is that the closure might survive the loop , and therefore someone might invoke it later , incorrectly expecting that the variable captured in the closure was captured by value. 唯一相关的是, 闭包可能在循环中幸存下来 ,因此有人可能稍后再调用它 ,错误地期望闭包中捕获的变量是按值捕获的。

Resharper has no way to know that a particular implementation of Select does not stash away the selector for later; Resharper无法知道Select的特定实现不会隐藏选择器以供以后使用。 in fact, that is exactly what all of them do . 实际上,这正是他们所有人所做的 How is Resharper supposed to know that they happen to stash it away in a place that won't be accessible later? Resharper应该如何得知他们碰巧将其藏在一个以后无法访问的地方?

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

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

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

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