문제
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
대표단 창조 시점의 가치보다는.
요컨대, 그것은 잠재적인 함정이지만이 경우에는 해를 끼치 지 않습니다.
참조 이 페이지의 하단 결과가 반 직관적 인 더 복잡한 예를 위해서.
다른 팁
나는 이것이 오래된 질문이라는 것을 알고 있지만 최근에 폐쇄를 연구하고 있으며 코드 샘플이 유용 할 수 있다고 생각했습니다. 무대 뒤에서 컴파일러는 기능 호출에 대한 어휘 폐쇄를 나타내는 클래스를 생성합니다. 아마도 다음과 같습니다.
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;
}
반면에, 당신이 저장하고 나중에 Predicates를 호출한다면, 당신은 predicates에 대한 모든 단일 호출이 실제로 폐쇄 클래스의 동일한 인스턴스에서 동일한 방법을 호출 할 것이므로 동일한 값을 사용한다는 것을 알 수 있습니다. 나.
"파일"은 a입니다 캡처 된 외부 변수 익명의 대의원 함수에 의해 캡처 되었기 때문입니다. 평생은 익명의 대의원 기능에 의해 확장됩니다.
캡처 된 외부 변수 외부 변수가 익명 함수에 의해 참조되면, 외부 변수는 익명 함수에 의해 캡처되었다고합니다. 일반적으로 로컬 변수의 수명은 블록이 관련된 블록 또는 명령문의 실행 (로컬 변수)으로 제한됩니다. 그러나, 캡처 된 외부 변수의 수명은 익명 함수에서 생성 된 대의원 또는 표현식 트리가 쓰레기 수집에 적합해질 때까지 확장됩니다.
로컬 변수 또는 값 매개 변수가 익명 함수에 의해 캡처되면, 로컬 변수 또는 매개 변수는 더 이상 고정 변수 (고정 및 움직일 수있는 변수)로 간주되지 않고 이동 가능한 변수로 간주됩니다. 따라서 캡처 된 외부 변수의 주소를 취하는 안전하지 않은 코드는 먼저 변수를 고정하려면 고정 문을 사용해야합니다. 캡처되지 않은 변수와 달리 캡처 된 로컬 변수는 여러 실행 스레드에 동시에 노출 될 수 있습니다.