简体   繁体   English

访问Modified Closure

[英]Access to Modified Closure

string [] files = new string[2];
files[0] = "ThinkFarAhead.Example.Settings.Configuration_Local.xml";
files[1] = "ThinkFarAhead.Example.Settings.Configuration_Global.xml";

//Resharper complains this is an "access to modified closure"
for (int i = 0; i < files.Length; i++ )
{
    // Resharper disable AccessToModifiedClosure
    if(Array.Exists(Assembly.GetExecutingAssembly().GetManifestResourceNames(),
    delegate(string name) { return name.Equals(files[i]); }))
         return Assembly.GetExecutingAssembly().GetManifestResourceStream(files[i]);
    // ReSharper restore AccessToModifiedClosure
}

The above seems to work fine though ReSharper complains that this is "access to modified closure". 虽然ReSharper抱怨这是“访问修改后的闭包”,但上述情况似乎工作正常。 Can any one shed light on this? 任何人都可以阐明这一点吗?

(this topic continued here ) (这个主题在这里继续)

In this case, it's okay, since you are actually executing the delegate within the loop. 在这种情况下,没关系,因为您实际上是循环中执行委托。

If you were saving the delegate and using it later, however, you'd find that all of the delegates would throw exceptions when trying to access files[i] - they're capturing the variable i rather than its value at the time of the delegates creation. 但是,如果您要保存委托并稍后使用它,您会发现所有委托在尝试访问文件时都会抛出异常[i] - 它们捕获变量 i而不是它的值。代表创作。

In short, it's something to be aware of as a potential trap, but in this case it doesn't hurt you. 简而言之,它应该被视为潜在的陷阱,但在这种情况下,它不会伤害到你。

See the bottom of this page for a more complex example where the results are counterintuitive. 有关更复杂的结果,请参见本页底部 ,其结果是违反直觉的。

I know this is an old question, but I've recently been studying closures and thought a code sample might be useful. 我知道这是一个老问题,但我最近一直在研究闭包,并认为代码示例可能有用。 Behind the scenes, the compiler is generating a class that represents a lexical closure for your function call. 在幕后,编译器生成一个类,表示函数调用的词法闭包。 It probably looks something like: 它可能看起来像:

private sealed class Closure
{
    public string[] files;
    public int i;

    public bool YourAnonymousMethod(string name)
    {
        return name.Equals(this.files[this.i]);
    }
}

As mentioned above, your function works because the predicates are invoked immediately after creation. 如上所述,您的函数有效,因为谓词在创建后立即被调用。 The compiler will generate something like: 编译器将生成如下内容:

private string Works()
{
    var closure = new Closure();

    closure.files = new string[3];
    closure.files[0] = "notfoo";
    closure.files[1] = "bar";
    closure.files[2] = "notbaz";

    var arrayToSearch = new string[] { "foo", "bar", "baz" };

    //this works, because the predicates are being executed during the loop
    for (closure.i = 0; closure.i < closure.files.Length; closure.i++)
    {
        if (Array.Exists(arrayToSearch, closure.YourAnonymousMethod))
            return closure.files[closure.i];
    }

    return null;
}

On the other hand, if you were to store and then later invoke the predicates, you would see that every single call to the predicates would really be calling the same method on the same instance of the closure class and therefore would use the same value for i. 另一方面,如果你要存储然后再调用谓词,你会发现对谓词的每次调用都会在闭包类的同一个实例上调用相同的方法,因此会使用相同的值一世。

"files" is a captured outer variable because it has been captured by the anonymous delegate function. “files”是一个捕获的外部变量,因为它已被匿名委托函数捕获。 Its lifetime is extended by the anonymous delegate function. 它的生命周期由匿名委托函数扩展。

Captured outer variables When an outer variable is referenced by an anonymous function, the outer variable is said to have been captured by the anonymous function. 捕获的外部变量当外部变量由匿名函数引用时,外部变量被称为已由匿名函数捕获。 Ordinarily, the lifetime of a local variable is limited to execution of the block or statement with which it is associated (Local variables). 通常,局部变量的生命周期限于执行与之关联的块或语句(局部变量)。 However, the lifetime of a captured outer variable is extended at least until the delegate or expression tree created from the anonymous function becomes eligible for garbage collection. 但是,捕获的外部变量的生命周期至少会延长,直到从匿名函数创建的委托或表达式树符合垃圾回收的条件。

Outer Variables on MSDN MSDN上的外部变量

When a local variable or a value parameter is captured by an anonymous function, the local variable or parameter is no longer considered to be a fixed variable (Fixed and moveable variables), but is instead considered to be a moveable variable. 当匿名函数捕获局部变量或值参数时,局部变量或参数不再被视为固定变量(固定和可移动变量),而是被视为可移动变量。 Thus any unsafe code that takes the address of a captured outer variable must first use the fixed statement to fix the variable. 因此,任何获取捕获的外部变量的地址的不安全代码必须首先使用fixed语句来修复变量。 Note that unlike an uncaptured variable, a captured local variable can be simultaneously exposed to multiple threads of execution. 请注意,与未捕获的变量不同,捕获的局部变量可以同时暴露给多个执行线程。

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

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