이벤트 처리기에 람다 식 사용


114

현재 다음과 같이 선언 된 페이지가 있습니다.

public partial class MyPage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //snip
        MyButton.Click += (o, i) =>
        {
            //snip
        }
    }
}

최근에야 1.1에서 .NET 3.5로 이동했기 때문에 Page_Load 외부에서 이벤트 처리기를 작성하는 데 익숙합니다. 내 질문은; 이를 위해 람다 메서드를 사용할 때주의해야 할 성능 단점이나 함정이 있습니까? 확실히 더 간결하기 때문에 선호하지만 사용하기 위해 성능을 희생하고 싶지는 않습니다. 감사.

답변:


117

컴파일러가 람다 식을 동등한 대리자로 변환하므로 성능에 영향을주지 않습니다. Lambda 표현식은 컴파일러가 작업하는 데 익숙한 것과 똑같은 코드로 번역하는 언어 기능에 지나지 않습니다.

컴파일러는 가지고있는 코드를 다음과 같이 변환합니다.

public partial class MyPage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //snip
        MyButton.Click += new EventHandler(delegate (Object o, EventArgs a) 
        {
            //snip
        });
    }
}

내가 참조. 따라서 이러한 핸들러를 Page_Load 내부에 두는 것과 외부에 두는 것의 단점도 없습니까?
Christopher Garcia

1
일반적인 규칙은 OnInit메서드 에 이벤트 핸들러를 연결 하는 것이지만 Click페이지가로드 된 후 버튼의 이벤트가 발생하므로이 예제는 괜찮습니다.
Andrew Hare

8
대리자에 대한 참조를 유지하지 않으면 이벤트 구독을 취소 할 수 없습니다.
snarf

3
"정확히 동일한 코드"는 약간 오해의 소지가 있습니다. 적어도 둘러싸는 메서드에서 지역 변수를 참조 할 때 람다 식은 메서드 지역 변수의 현재 값을 저장하는 클로저 객체와 같은 것으로 변환되지 않습니다 .
또는 Mapper

66

성능면에서는 명명 된 메서드와 동일합니다. 큰 문제는 다음을 수행 할 때입니다.

MyButton.Click -= (o, i) => 
{ 
    //snip 
} 

아마도 다른 람다를 제거하고 원래는 그대로 두려고 할 것입니다. 그래서 교훈은 핸들러를 제거 할 수 있기를 원하지 않는 한 괜찮다는 것입니다.


3
" 아마도 ..."? 그것은 것인가 지금까지 이러한 상황에서 올바른 처리기를 제거?
또는 Mapper

1
@ORMapper : 람다가 변수를 캡처하면 올바른 처리기를 제거 할 수 없습니다. 다른 상황에서는 컴파일러에 달려 있습니다.
Gabe

정말? 흥미 롭습니다. 똑같이 보이는 두 개의 익명 함수를 등록한 다음 (wlog에는 본문이 비어 있음) 본문이 비어있는 -=다른 익명 함수를 등록 해제 (사용 )하면 두 이벤트 처리기 중 어느 것이 제거 할 것인지 아니면 전혀 제거 할 것인지 여부?
또는 Mapper

4
@ORMapper : 네. 컴파일러는 동일한 의미 체계 (코드가 동일 할 필요는 없지만 동일한 작업을 수행해야 함)를 가진 경우 동일한 대리자를 만들 수 있으며 (반드시 그럴 필요는 없음) 동일한 변수 인스턴스를 캡처 할 수 있습니다. 동일한 변수이지만 해당 변수의 동일한 인스턴스). 자세한 내용은 C # 사양의 7.10.8 (대리자 같음 연산자) 섹션을 참조하세요.
Gabe

12
정말로 람다를 사용하고 싶지만 이벤트를 제거해야하는 경우 항상 지역 변수 / 필드에 개체를 유지 한 다음 제거 할 수 있습니다. 예var event = (o, e) => doSomething(); handler += event; doSomethingElse(); handler -= event;
Wai Ha Lee

44
EventHandler handler = (s, e) => MessageBox.Show("Woho");

button.Click += handler;
button.Click -= handler;

1
매우 유용한 정보이지만 주제와 관계가 없습니다 (문제는 성능에 관한 것입니다).
스테판 고리 촌

4
메모리 사용량이 성능 저하로 이어질 수 있으므로 주제에서 벗어난 것은 아닙니다.
블라 디우스

3
핸들러 자체에서 자신을 제거하는 것도 도움이 될 수 있습니다.c# EventHandler handler = null; handler = (s, e) => { MessageBox.Show("Woho"); button.Click -= handler;}
Vladius

2

"구문 적 설탕"을 알고 있고 델리게이트 구문 등을 사용하는 것과 동일한 것으로 컴파일하는 한, 내가 알고 있거나 경험 해본 성능 관련 문제는 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.