04
23
다음 본문은 도서 이펙티브 C# (빌 와그너)에서 나오는 주제를 다룹니다.

 

 

이벤트의 null 예외

이벤트를 호출하였을때, 결합된 이벤트 핸들러가 없다면 nullReference 예외가 발생한다.

 

때문에 예전에는 다음과 같은 방식으로 코드를 작성하였다.

public void Test()
{
    if(MyEvent != null)
        MyEvent(this, counter);
}

 그런데 이벤트를 발생시키는 코드를 수행하기 직전에 다른 쓰레드가 이벤트 핸들러의 등록을 취소한다면 이벤트 핸들러는 null 예외를 발생시킬 것이다. (재현도 어렵고 극단적인 케이스기는 하다)

 

이 때문에 멀티스레드 환경에서는 다음과 같은 코드로 오류를 방지했다.

public void Test()
{
    var tempHandler = MyEvent;
    if(tempHandler != null)
        tempHandler(this, counter);
}

지역변수에 이벤트 핸들러를 얕은 복사하여, 외부에서 다른 스레드가 원본의 이벤트 구독을 취소하더라도

복사된 지역변수에서는 남아있기때문에 정상호출된다.

 

null 조건 연산자

 - 해결책은 간단하다. null 조건 연산자를 사용하여 안전하게 이벤트 핸들러를 호출할 수 있다.

 - ?. 연산자를 이용하여 이벤트를 발생시킬때는 이벤트 이름뒤에 ()를 붙여 호출할 수 없다. Invoke로 호출해야한다.

public void Test()
{
    MyEvent?.Invoke(this, counter);
}

 

결론

 - 이벤트를 if문으로 null 검사하는 것은 구식 방식이며, 반드시 ?. 연산자를 이용하는 방식을 사용하라.

 

 

COMMENT