여기에 아무도 ECMA-334를 직접 인용하지 않았기 때문에 :
10.4.4.10 진술 문
양식의 진술에 대한 명확한 할당 검사 :
for (for-initializer; for-condition; for-iterator) embedded-statement
진술이 작성된 것처럼 수행됩니다.
{
for-initializer;
while (for-condition) {
embedded-statement;
LLoop: for-iterator;
}
}
또한 사양에서
12.16.6.3 지역 변수의 인스턴스화
로컬 변수는 실행이 변수 범위에 들어가면 인스턴스화되는 것으로 간주됩니다.
[예 : 예를 들어, 다음 메소드가 호출 x
되면 루프가 반복 될 때마다 로컬 변수 가 세 번 인스턴스화되고 초기화됩니다.
static void F() {
for (int i = 0; i < 3; i++) {
int x = i * 2 + 1;
...
}
}
그러나 x
루프 외부 에서 선언을 이동하면 단일 인스턴스화가 발생합니다 x
.
static void F() {
int x;
for (int i = 0; i < 3; i++) {
x = i * 2 + 1;
...
}
}
최종 예]
캡처되지 않은 경우, 로컬 변수의 인스턴스화 빈도를 정확하게 관찰 할 수있는 방법이 없습니다. 인스턴스화의 수명이 서로 다르기 때문에 각 인스턴스에서 동일한 스토리지 위치를 사용할 수 있습니다. 그러나 익명 함수가 로컬 변수를 캡처하면 인스턴스화의 효과가 분명해집니다.
[예 : 예
using System;
delegate void D();
class Test{
static D[] F() {
D[] result = new D[3];
for (int i = 0; i < 3; i++) {
int x = i * 2 + 1;
result[i] = () => { Console.WriteLine(x); };
}
return result;
}
static void Main() {
foreach (D d in F()) d();
}
}
출력을 생성합니다.
1
3
5
그러나의 선언이 x
루프 외부로 이동 된 경우 :
static D[] F() {
D[] result = new D[3];
int x;
for (int i = 0; i < 3; i++) {
x = i * 2 + 1;
result[i] = () => { Console.WriteLine(x); };
}
return result;
}
출력은 다음과 같습니다
5
5
5
컴파일러는 세 인스턴스화를 단일 델리게이트 인스턴스 (§11.7.2)로 최적화 할 수 있지만 필수는 아닙니다.
for-loop가 반복 변수를 선언하면 해당 변수 자체는 루프 외부에서 선언 된 것으로 간주됩니다. [예 : 따라서 반복 변수 자체를 캡처하도록 예를 변경 한 경우 :
static D[] F() {
D[] result = new D[3];
for (int i = 0; i < 3; i++) {
result[i] = () => { Console.WriteLine(i); };
}
return result;
}
반복 변수의 한 인스턴스 만 캡처되어 출력을 생성합니다.
3
3
3
최종 예]
오 예, C ++에서는 변수가 값 또는 참조로 캡처되는지 선택할 수 있기 때문에이 문제가 발생하지 않는다고 언급해야한다고 생각합니다 ( Lambda capture 참조 ).