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;
}
반면에 술어를 저장 한 다음 나중에 호출하면 술어에 대한 모든 단일 호출이 클로저 클래스의 동일한 인스턴스에서 실제로 동일한 메소드를 호출하므로 동일한 값을 사용한다는 것을 알 수 있습니다. 나는.
답변
“파일”은 익명 대리자 함수에 의해 캡처 되었기 때문에 캡처 된 외부 변수 입니다. 익명 위임 기능으로 수명이 연장됩니다.
캡처 된 외부 변수 외부 변수가 익명 함수에 의해 참조 될 때 외부 변수는 익명 함수에 의해 캡처되었다고합니다. 일반적으로 지역 변수의 수명은 지역 변수와 관련된 블록이나 명령문의 실행으로 제한됩니다. 그러나 익명 함수에서 작성된 대리자 또는 표현식 트리가 가비지 콜렉션에 적합해질 때까지 캡처 된 외부 변수의 수명이 연장됩니다.
로컬 변수 또는 값 매개 변수가 익명 함수에 의해 캡처되면 로컬 변수 또는 매개 변수는 더 이상 고정 변수 (고정 및 이동 가능 변수)로 간주되지 않지만 대신 이동 가능 변수로 간주됩니다. 따라서 캡처 된 외부 변수의 주소를 사용하는 안전하지 않은 코드는 먼저 고정 명령문을 사용하여 변수를 수정해야합니다. 캡처되지 않은 변수와 달리 캡처 된 로컬 변수는 여러 실행 스레드에 동시에 노출 될 수 있습니다.