"접근할 수 없는 코드" 컴파일 경고의 한계

부제 : C# 의 DateTime 은 value type 이다


Visual Studio 의 컴파일러가 탐지 해 주는 "접근할 수 없는 코드" 경고(Warning CS0162: Unreachable code detected) 는 무심코 작성한 잘못된 코드를 발견하는 데 도움을 줍니다. 


예) 접근할 수 없는 코드와 컴파일 경고

// 접근할 수 없는 코드
if (false)
{
  System.Console.WriteLine("Unreachable code");
}


그러나 이 경고만으로는 접근할 수 없는 코드를 탐지하지 못하는 경우도 있습니다.

static void Main(string[] args)
{
  DateTime myDateTime = new DateTime();
      
  if (myDateTime == null)
  {
    System.Console.WriteLine("myDateTime is null.");
  }
  else
  {
    System.Console.WriteLine("myDateTime is not null.");
  }
}

여러분의 눈에는 접근하지 못하는 코드가 바로 보이시나요?

솔직히 말하면, 저는 한 눈에 찾아 내지 못해서 한참을 헤맸습니다.


우선 위 코드를 디버깅 하기 위해 "else" 에 중단점을 삽입하면, 자꾸만 if 문에 중단점이 걸리는 것을 볼 수 있습니다. 마치 Visual Studio 가 중단점을 잘못 걸고 있는 것 처럼 보입니다.


else 문이 있는데

왜 중단점 설정을 못하니.. ㅜㅜ


(이미 부제에 다 나와 있지만) 왜 중단점이 안걸리는걸까요? 정답을 말하기 전에 ILSpy 를 이용하여 빌드 결과를 관찰 해 보겠습니다.

참고로 ILSpy 는 컴파일 된 모듈(실행파일 또는 dll)을 디컴파일 하여 C# 코드로 볼 수 있게 도와 주는 프로그램입니다. 다른 사람이 만든 모듈에서 코드를 복원해야 하거나, 지금처럼 빌드 된 모듈을 살펴보고 싶을 때 이용할 수 있습니다.


bin/debug 경로에 빌드 되어 있는 실행파일을 디컴파일 한 모습입니다. 분기문이 없이 무조건 else 문 내부만 실행하도록 되어 있습니다. flag 를 항상 true 로 설정하고 있는 것도 눈에 띄네요.


이는 DateTime 이 reference type 이 아니라 value type 이기 때문입니다. value type 은 기본형타입과 동일하게 not nullable 입니다. 따라서 if(myDateTime == null) 은 항상 false 값이 되니, 컴파일러는 이 분기문이 필요 없다고 생각하고 과감하게 생략하여 컴파일 해 버린 것입니다. 생략 하면서 "접근할 수 없는 코드" 경고까지 남겨 주었다면 참 고마울텐데, 그정도로 친절하지는 않네요. 도도한 컴파일러 녀석 같으니...


만약 Value Type 이 null 값을 갖고자 한다면 변수 선언 시 타입 뒤에 ?(nullable) 를 붙여 줘야 합니다. ?를 붙이고 나면 아래처럼 빌드 결과에도 null check 분기문이 반영 됩니다.


작성한 C# 코드

static void Main(string[] args)
{
  DateTime? myDateTime = new DateTime();
      
  if (myDateTime == null)
  {
    System.Console.WriteLine("myDateTime is null.");
  }
  else
  {
    System.Console.WriteLine("myDateTime is not null.");
  }
}

빌드 결과


혹시 관심이 있으신 분은 new DateTime() 으로 객체를 생성 할 때 new DateTime?() 으로 생성 해 보시기 바랍니다. 빌드 결과가 달라지는 것을 볼 수 있습니다.


저는 다른 사람이 작성한 코드를 분석하다가 작성된 C# 코드와 빌드된 dll 이 달라서 헤매고 난 뒤 이번 글을 쓰게 되었습니다. 하지만 앞으로 이 내용을 활용하는 경우가 있다면 중단점이 제대로 걸리지 않거나, DateTime? 를 이용해야 할 때 일 것 같네요. Debugging 을 하다가 중단점이 걸리지 않는 문제를 만나신 분, 또는 DateTime 의 null 조건을 검사하고자 하는 분께 이 글이 도움이 되기를 바랍니다.


그리고 마지막으로, java.util.Date 는 reference type 이므로 nullable 입니다. 참고하세요^^