Monday, May 27, 2013

Closure 쓸 때 주의할 점

지난 포스트에 이어서...

var list = new List<int>(10);
var menu = new ToolStripMenuItem("메뉴");
for(int i=0; i<list.Count; i++) {
     var subMenu = new ToolStripMenuItem("메뉴 항목");
     subMenu.Click += ( (sender, args)=>{ subMenu_Click(sender, i); } ); // closure
}
void subMenu_Click(object sender, int idx)
{
     MessageBox.Show(string.Format("{0}이 클릭됨", idx));
}

예상되는 결과는? i번째 subMenu를 누르면 i가 출력되지 않는다.

다음과 같이 변수를 한 번 복사하는 게 해결책이다:

for(int i=0; i<list.Count; i++) {
     var subMenu = new ToolStripMenuItem("메뉴 항목");
   int j=i; // 이거면 되지 않을까 했는데 진짜 됐음-_-乃
     subMenu.Click += ( (sender, args)=>{ subMenu_Click(sender, j); } ); // closure
}

해결하고 나서 stackoverflow에 질문을 올렸는데

Google: passing parameter evenhandler value changes C#

이걸로 검색하니까 금방 나옴.

역시 원리는 안 찾아보고 하니까 이유는 모른다.

아래 링크에 이유가 있다고 하는데 읽기는 귀찮다.
http://stackoverflow.com/questions/2226510/closures-in-c-sharp-event-handler-delegates
http://stackoverflow.com/questions/271440/c-sharp-captured-variable-in-loop

No comments:

Post a Comment

"Gossip Girl" star Michelle Trachtenberg dies at 39

미셸 트랙튼버그 하우스에서 심장 이식 받았던 환자로 나왔는데 현실에서는 간이식을 받았었구나 가십걸이나 버피더뱀파이어슬레이어 이제 정주행해 볼까... 블로그도 다시 살려 볼까 훠훠