IT이야기

익명 이벤트 핸들러 추가 및 제거

cyworld 2021. 9. 29. 21:42
반응형

익명 이벤트 핸들러 추가 및 제거


이것이 실제로 효과가 있었는지 궁금합니다.

private void RegisterKeyChanged(T item) 
{
    item.OnKeyChanged += (o, k) => ChangeItemKey((T)o, k);
}

private void UnRegisterKeyChanged(T item) 
{
    item.OnKeyChanged -= (o, k) => ChangeItemKey((T)o, k);
}

컴파일러는 이벤트 핸들러가 동일하다는 것을 어떻게 알 수 있습니까? 이것도 추천인가요?


이에 대해 설명하는 MSDN 페이지가 있습니다.

이벤트 구독 및 구독 취소 방법

특히 참고:

나중에 [원문 그대로] 이벤트 구독을 취소할 필요가 없으면 더하기 할당 연산자(+=)를 사용하여 이벤트에 익명 메서드를 연결할 수 있습니다.

그리고 또한:

익명 함수를 사용하여 이벤트를 구독한 경우 이벤트에서 쉽게 구독을 취소할 수 없다는 점에 유의하는 것이 중요합니다. 이 시나리오에서 구독을 취소하려면 이벤트를 구독하는 코드로 돌아가서 대리자 변수에 익명 메서드를 저장한 다음 이벤트에 대리자를 추가해야 합니다. 일반적으로 나중에 코드에서 이벤트 구독을 취소해야 하는 경우 이벤트 구독에 익명 함수를 사용하지 않는 것이 좋습니다.


관심 있는 사람은 다음과 같이 익명 이벤트 처리기를 추가 및 제거할 수 있습니다.

public class Musician
{
    public void TuneGuitar()
    {
        Metronome metronome = new Metronome();

        EventHandler<EventArgs> handler = null;
        handler = (sender, args) =>
        {
            // Tune guitar
            // ...

            // Unsubscribe from tick event when guitar sound is perfect
            metronome.Tick -= handler;
        };

        // Attach event handler
        metronome.Tick += handler;
    }
}

public class Metronome
{
    event EventHandler<EventArgs> Tick;
}

업데이트: C# 7.0에서는 로컬 함수를 지원 하므로 TuneGuitar이제 메서드를 다음과 같이 작성할 수 있습니다.

public void TuneGuitar()
{
    Metronome metronome = new Metronome();

    void handler(object sender, EventArgs args)
    {
        // Tune guitar
        // ...

        // Unsubscribe from tick event when guitar sound is perfect
        metronome.Tick -= handler;
    };

    // Attach event handler
    metronome.Tick += handler;
}

If you need to unsubscribe an event handler, you'll need to have a definite reference to a concrete delegate. Looking at Delegate.Equality you will find that delegates aren't just compared using reference equality, however this doesn't matter for anonymous delegates.

For an anonymous delegate, the compiler (basically) just creates a new "non-anonymous" delegate for each anonymous delegate, even if the delegate bodies are the same. Because of this, the framework will not find the delegate to unsubscribe when you use the code example you gave.


That won't work I'm afraid, since the two lambda expressions (and delegates) that you declared are actually different objects, and return different references. Hence, the removal of the handler (-=) will always fail.

The common solution to this problem (where you need to remove the handler) is simply to refactor the lamba expression into a proper method. An alternative is to maintain a class variable for the event handler delegate, and add and remove this, though I am personally not a fan of it. (It's more hassle than just creating a normal method, if anything.)


I don't believe this will work. If you really need to unregister from an event you must specify an explicit event handler which you can later unregister from instead of an anonymous delegate.


If you check with the document for Delegate.Equality, you would find out they are not compared by reference.

ReferenceURL : https://stackoverflow.com/questions/2051357/adding-and-removing-anonymous-event-handler

반응형