ITEM 8 :: EFFECTIVE C#
안녕하세요, 8번째 시간입니다. 8은 중국에서 행운의 숫자라고 하죠?
이번 챕터에도 역시 C#에서의 새로운 연산자가 나옵니다! 새로운 걸 접하는 것은 언제나 어렵지만 재미도 있는 법이지요. 나만 그런가? 이번에 설명드릴 연산자는 C# 6.0에 새롭게 추가된 Null 조건 연산자라는 것입니다. 이걸 어디에 쓰냐, 하면, 과거의 이야기를 조금 해야합니다. 자, 설명 들어가겠습니다.
설명
- null 조건 연산자가 없을 때, 과거에는 null check 방식을 사용했다. 방식이라고 하면 거창하고, 단순하게 이벤트 호출전에 널을 검사했다는 것이다.
- 검사한 이유는 이벤트 핸들러를 통해 이벤트를 호출 할 때 넘겨받은 인자가 Null일 경우에는 당연히 안되기 때문에 검사를 하는 것이고,
- 추가적으로 다른 스레드에서 값을 넘기고 나서 이벤트 핸들러를 취소할 경우 NullReferenceException이 발생하므로, 이러한 Check 방식이 필요하다!
그래서 나온 null 조건 연산자
- 이를 사용하면, 다른 스레드에서 값을 넘기고 나서 이벤트 핸들러를 취소하더라도, 이미 널 검사를 조건 연산자가 해주기 때문에, 예외가 발생하지 않는다.
- 가독성이 매우 좋아진다. ( 이를 사용하지않고, NullCheck를 하드코딩으로 작성할 시, 보기도 힘들고, 이벤트 호출시마다 넣어줘야 하므로 번거롭다. 이를 사용하면 한줄로 끝난다!)
- 사용방법은 아래의 New 주석부분을 참고하면 좋을 것 같다. (? 연산자가 바로 Null 조건 연산자이다. Invoke는 접근하고자 하는 윈도우의 쓰레드가 아닌, 다른 쓰레드에서 이 윈도우에 접근을 시도할 때, 에러를 발생시키는데, 이 에러를 없앨 때 사용하는 함수이다.)
// 구식적인 방법. Updated가 null이 아니여서 if 구문에 들어올때,
// 다른 스레드에서 이벤트 핸들러를 취소할경우 NullReferenceException이 발생.
public void RaiseUpdates()
{
counter++;
if(Updated != null)
Updated(this, counter);
}
// NEW!: null 조건 연산자를 이용하면 멀티스레딩 환경에도 안전하다.
public void RaiseUpdates()
{
counter++;
Updated?.Invoke(this, counter); // 함수를 Invoke를 통해 불렀을 때, Null이 발생할 경우 ? 조건연산자에 의해 해당 절은 무시되고 다음절로 넘어가게된다.
}
정리
멀티 스레딩 상황이나, 이벤트 핸들러 호출부분의 Null Check를 할 때 지저분한 코드를 계속해서 복사해 사용하는 것 보다, 이 방식을 사용하면 한줄로 대부분이 정리된다. 이전부터 있었던 문제인 탓에 예전 방식으로 해결된 해결책들이 인터넷에는 굉장히 많을 것으로 생각된다. 하지만, 그럼에도 구식의 것보다는 이 널 조건연산자를 사용하는 것이 명확하고 가독성이 좋으며, 예외처리에 완벽하므로 이것을 사용하는 것이 좋다!