이번 포스트는 개인적으로 쓸까 말까 고민을 많이 했다. 읽다 보면 알게 되겠지만 이게 무슨 개소린가 싶은 전처리 문법이 C# 8.0에 추가 되었다.
nullable 값 형식
C#에서 값 타입 변수에 null을 대입하면 오류가 나지만 타입 뒤에 물음표(?)를 붙여주면 "nullable 허용 값 형식"이라고 값을 가지는 변수지만 null을 지정 할 수도 있다.
int m1 = 10; // 정상
int m2 = null; // 에러
int? m3 = null; // 정상
물론 string과 같은 참조 타입 변수는 null을 대입해도 아무런 문제가 없다.
string s = null;
int len = s.Length; // exception
그런데 문제는 이렇게 null 값을 대입 할 수 있도록 해놓으니 위 처럼 null을 가리키고 있는 객체를 그냥 쓰다 예외가 발생하는 경우가 적지 않았다는 것이다.
그에 대한 대책으로 모든 참조 변수를 null을 가리키지 않고 객체를 가진 상태로 초기화하지 않으면 컴파일 시 경고를 출력하는 전처리를 추가 할 수 있게 되었다.
#nullable enable // 참조 타입 변수라도 null을 대입하면 경고
string s1 = null; // 경고 : null 리터럴 또는 가능한 null 값을 null을 허용하지 않는 형식으로 변환하는 중입니다.
string? s2 = null; // nullable 전처리 중이지만 null 허용
string notNull = "Hello";
string? nullable = null; // 또는 default
notNull = nullable!; // 허용됨
#nullable disable // nullable 전처리 비활성화
하지만 타입 뒤에 물음표를 붙이면 역시 null을 허용한다. null을 참조 할 수 있도록 하니 문제가 발생해서 그것을 막아 보려고 nullable 전처리를 추가했다가, 다시 그게 불편하니 또 물음표를 타입 뒤에 붙여 null을 가능하게 하는..
뭔가 점점 더 복잡해진다.
마치며
안정성도 잡고 싶고 그러다 보니 편의성이 해쳐져서 다시 편의를 넣은 마음은 알겠는데...이거는 참으로 혼란하다.
암튼 정리는 해야 하니..nullable 인식 컨텍스트에서:
- 참조 형식 T의 변수는 null이 아닌 값으로 초기화되어야 하며, null일 수 있는 값을 할당할 수 없다.
- 참조 형식 T?의 변수는 null로 초기화되거나 null이 할당될 수 있지만, 역참조하기 전에 null에 대해 확인되어야 한다.
- m!(위 예에서 nullable!)의 경우와 같이 null 허용 연산자를 적용하면 T? 형식(string?)의 m 변수는 null이 아닌 것으로 간주한다.
정도로 요약 할 수 있겠다.