訪問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 ) (這個主題在這裏繼續)


#1樓

參考:https://stackoom.com/question/zFf/訪問Modified-Closure


#2樓

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. 另一方面,如果你要存儲然後再調用謂詞,你會發現對謂詞的每次調用都會在閉包類的同一個實例上調用相同的方法,因此會使用相同的值一世。


#3樓

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. 有關更復雜的結果,請參見本頁底部 ,其結果是違反直覺的。


#4樓

"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. 請注意,與未捕獲的變量不同,捕獲的局部變量可以同時暴露給多個執行線程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章