C# 访问修改后的关闭

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/235455/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 19:16:51  来源:igfitidea点击:

Access to Modified Closure

c#resharperclosures

提问by Vyas Bharghava

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". Can any one shed light on this?

尽管 ReSharper 抱怨这是“访问修改后的闭包”,但上述内容似乎工作正常。任何人都可以阐明这一点吗?

(this topic continued here)

(这个话题在这里继续)

采纳答案by Jon Skeet

In this case, it's okay, since you are actually executing the delegate withinthe 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 variableirather than its value at the time of the delegates creation.

但是,如果您保存委托并稍后使用它,您会发现所有委托在尝试访问 files[i] 时都会抛出异常 - 它们捕获的是变量i而不是委托时的值创建。

In short, it's something to be aware of as a potentialtrap, but in this case it doesn't hurt you.

简而言之,这是一个需要注意的潜在陷阱,但在这种情况下,它不会伤害您。

See the bottom of this pagefor a more complex example where the results are counterintuitive.

有关结果违反直觉的更复杂示例,请参阅本页底部

回答by gerrard00

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.

另一方面,如果您要存储然后稍后调用谓词,您会看到对谓词的每次调用实际上都会在闭包类的同一实例上调用相同的方法,因此将使用相同的值一世。

回答by chris hu

"files" is a captured outer variablebecause it has been captured by the anonymous delegate function. Its lifetime is extended by the anonymous delegate function.

“files”是一个捕获的外部变量,因为它已被匿名委托函数捕获。它的生命周期由匿名委托函数延长。

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. Note that unlike an uncaptured variable, a captured local variable can be simultaneously exposed to multiple threads of execution.

当匿名函数捕获局部变量或值参数时,局部变量或参数不再被视为固定变量(Fixed and moveable variables),而是被视为可移动变量。因此,任何获取捕获的外部变量地址的不安全代码必须首先使用 fixed 语句来修复变量。请注意,与未捕获的变量不同,捕获的局部变量可以同时暴露给多个执行线程。