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의 역할을 하는 변수를 추가하고 그 변수를 참조하게 되었음.

 

📒참고 문서