C# 의 Nullable Types

프로그래밍을 하다 보면 성가신 것 중 하나가 null이 나 범위를 벗어난 데이터와 같은 잘못된 데이터의 처리입니다. 저 같은 경우 Jakarta Commons Lang이나 TL-Util, 그도 아니면 그냥 직접 일일이 코딩하곤 합니다.

잘못된 데이터가 들어왔을 경우 취할 수 있는 행동은

  • 예외를 던진다
    • NullPointerException – null 인 경우
    • IllegalArgumentException – null은 아니나 규약 위반인 경우
    • 기타 사용자 정의 예외 – RuntimeException 상속
    • AssertionError – assert 문 사용시
      • 매우 편리
      • 외부 노출시 사용 불가
      • JDK 1.4 이상에서만 사용 가능
  • 예외를 던지지 않고 기본 값으로 조용히 치환해 처리한다

정도가 있겠습니다.

그런데, 이번 Visual Studio 2005 에서 등장한 C# 의 Nullable 타입은 예외를 던지지 않고 null 값을 적절히 처리할 수 있도록 돕고 있습니다. 모든 타입 선언은 타입명 뒤에 ? 오퍼레이터를 붙여 Nullable 이 될 수 있습니다:

int? x = 123;
int? y = null;
if (x.HasValue) Console.WriteLine(x.Value); // Printed
if (y.HasValue) Console.WriteLine(y.Value); // Not Printed

Nullable 과 일반 타입 간의 변환은 자유롭습니다:

int i = 123;
int? x = i; // int –> int?
double? y = x; // int? –> double?
int? z = (int?)y; // double? –> int?

// DOWNCAST: Throws exception if z is null.
int j = (int)z; // int? –> int

Nullable 간 연산은 매우 유용해 보입니다:

int? x = GetNullableInt();
int? y = GetNullableInt();

// Two statements do the same job.
int? z = x.HasValue && y.HasValue ? x.Value + y.Value : (int?)null;
int? z = x + y;

?? 연산자를 이용한 디폴트 값 치환은 손가락을 덜 피곤하게 하겠군요:

string s = GetStringValue();

// Print ‘Unspecified’ if s is null
Console.WriteLine(s ?? “Unspecified”);

한편으로는 물음표 하나 늘어났을 뿐이지만 언어가 점점 더 복잡해 지고 있는 것은 아닌가 싶은 생각도 듭니다. 하지만 시간이 지날 수록 언어의 구성 요소가 위와 같이 API 와 결합하여 더 강력한 효과를 내는 것이 요즘의 추세이고, 그에 따라 언어와 API 의 경계가 모호해고 있습니다. 남이 작성한 코드를 읽다가 모르는 API 가 나오면 이해하기 위해 학습해야 하듯, 이런 새로운 언어 요소들도 마찬가지가 아닌가 생각해 봅니다.