⭐ 캡쳐와 클로저
람다식이나 익명 메서드가 자신이 선언된 스코프 밖에 있는 지역 변수의 값을 복사하는 것이 아닌 변수 자체를 잡아두는 것을 캡쳐라고 합니다.
위처럼 외부 변수를 캡쳐한 함수 그 자체를 클로저라고 부릅니다.
● 캡쳐 = 외부 변수를 잡아두는 행위
● 클로저 = 캡쳐가 발생한 변수
왜 일어날까?
● 람다식, 익명 메서드가 지역변수를 사용 후 사라져야 하지만 람다는 여전히 그 지역 변수를 필요로 합니다.
○ 컴파일러가 별도의 힙 객체를 만들어 참조
○ 람다, 익명 메서드가 살아있는 한 외부 변수가 GC로 수거되지 않고 값 변경도 그대로 반영됨 → 문제 발생
Action action;
private void Start()
{
for(int i = 0; i < 5; i++)
{
action += () => Debug.Log(i);
}
action?.Invoke();
}
출력 결과:
5
5
5
5
5
● 분명 반복문을 통해 출력하고자 한 값은 0부터 4까지 출력되도록 하는 것이지만 캡쳐가 일어나 엉뚱한 결과가 출력됐습니다.
○ 반복문에서 선언한 변수 i에 캡쳐가 일어나 action에 들어간 람다식의 i들은 모두 같은 힙 메모리의 객체를 참조하고 있습니다.
○ 0부터 4까지 반복된 후 마지막으로 i++을 통해 i는 5가 되었기 때문에 모두 5가 출력됩니다.
● 위와 같은 문제를 해결하기 위해 따로 지역변수를 선언하여 넣어줍니다.
○ 반복문 내에 새로운 지역변수를 선언하여 해당 변수를 출력하도록 합니다.
해결 방법
Action action;
private void Start()
{
for(int i = 0; i < 5; i++)
{
int temp = i;
action += () => Debug.Log(temp);
}
action?.Invoke();
}
출력 결과:
0
1
2
3
4'개발, IT > C#' 카테고리의 다른 글
| [유니티 / C# ] 리스트(List)와 연결 리스트(Linked List) (0) | 2025.09.24 |
|---|---|
| [유니티 / C#] 인덱서 (Indexer) (0) | 2025.09.23 |
| [유니티 / C#] 가변 인자 params (0) | 2025.09.23 |
| [유니티 / C#] 확장 메서드 (Extension Method) (0) | 2025.09.22 |
| [유니티 / C#] 대리자 (Delegate, Event, Action, Function) (0) | 2025.09.22 |