[C#] 수정 된 폐쇄에 대한 액세스

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
}

ReSharper가 이것이 “수정 된 폐쇄에 대한 액세스”라고 불평하지만 위의 내용은 잘 작동하는 것 같습니다. 아무도 이것에 빛을 비출 수 있습니까?

(이 주제는 여기서 계속 되었습니다 )



답변

이 경우 실제로 루프 에서 대리자를 실행하기 때문에 괜찮습니다 .

그들은 캡처하고 – 당신이 대리자를 저장하고 나중에 사용한 경우 [I] 파일에 액세스하려고 할 때, 그러나, 당신은 대의원의 모든 예외를 슬로우 찾을 거라고 변수를 i 대표시 값보다는 창조.

요컨대, 그것은 잠재적 인 함정 으로 알고 있어야 하지만이 경우 당신을 해치지 않습니다.

결과가 반 직관적 인보다 복잡한 예 는이 페이지하단을 참조하십시오 .


답변

나는 이것이 오래된 질문이라는 것을 알고 있지만 최근에 클로저를 연구하고 코드 샘플이 유용 할 것이라고 생각했습니다. 뒤에서 컴파일러는 함수 호출에 대한 어휘 폐쇄를 나타내는 클래스를 생성합니다. 아마도 다음과 같습니다.

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

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

위에서 언급했듯이, 술어는 작성 직후에 호출되므로 함수가 작동합니다. 컴파일러는 다음과 같은 것을 생성합니다 :

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

반면에 술어를 저장 한 다음 나중에 호출하면 술어에 대한 모든 단일 호출이 클로저 클래스의 동일한 인스턴스에서 실제로 동일한 메소드를 호출하므로 동일한 값을 사용한다는 것을 알 수 있습니다. 나는.


답변

“파일”은 익명 대리자 함수에 의해 캡처 되었기 때문에 캡처 된 외부 변수 입니다. 익명 위임 기능으로 수명이 연장됩니다.

캡처 된 외부 변수 외부 변수가 익명 함수에 의해 참조 될 때 외부 변수는 익명 함수에 의해 캡처되었다고합니다. 일반적으로 지역 변수의 수명은 지역 변수와 관련된 블록이나 명령문의 실행으로 제한됩니다. 그러나 익명 함수에서 작성된 대리자 또는 표현식 트리가 가비지 콜렉션에 적합해질 때까지 캡처 된 외부 변수의 수명이 연장됩니다.

MSDN의 외부 변수

로컬 변수 또는 값 매개 변수가 익명 함수에 의해 캡처되면 로컬 변수 또는 매개 변수는 더 이상 고정 변수 (고정 및 이동 가능 변수)로 간주되지 않지만 대신 이동 가능 변수로 간주됩니다. 따라서 캡처 된 외부 변수의 주소를 사용하는 안전하지 않은 코드는 먼저 고정 명령문을 사용하여 변수를 수정해야합니다. 캡처되지 않은 변수와 달리 캡처 된 로컬 변수는 여러 실행 스레드에 동시에 노출 될 수 있습니다.


답변