Unity
for 문으로 AddListener 이벤트를 등록 시 주의할 점. Closure(클로저)
JiHxxn
2024. 2. 12. 14:24
👇 문제
for(int i = 0; i > buttons.Length; i ++)
{
buttons.onClick.AddListener(() => OnClickButton_PlayerSet(i));
}
이러한 5개의 버튼 배열을 선언해놓은 후 AddListener로 할당하려 했을 때 결과 값으로 i의 마지막 값으로 모두 초기화 되는 현상이 있다.
👇 문제 해결 방법
for(int i = 0; i > buttons.Length; i ++)
{
int index = i;
buttons.onClick.AddListener(() => OnClickButton_PlayerSet(index));
}
Closure 문제 때문에 복사해서 사용한다. (5개의 index는 힙에 할당됨)
🤔 Closure(클로저) 란?
람다 식을 구현할 때 람다 식 외부에서 선언한 변수를 사용할 때 컴파일러는 캡처링(Capturing)이라는 작업을 통해 이에 사용할 함수와 변수의 집합을 생성하는데, 이들을 클로저(Closure)라 한다.
👨💻 예제 코드
int temp = 10;
Func<int, int> add = x => (x + temp);
Console.WriteLine(add(5)); // Output 15
temp = 20;
Console.WriteLine(add(5)); // Output 25
🧐 문제 이유
for문에서 i는 for문이 끝나면 삭제되는 변수였지만, 람다식으로 i를 이벤트에 포함 시켜버렸기 때문.
i는 스택에 있는 변수였지만 힙에 i의 역할을 하는 변수를 추가하고 그 변수를 참조하게 되었음.