본문 바로가기
C#

[C#] Nullable 사용법

by 대박플머 2014. 6. 19.

Nullable 처음 들어본 사람도 있을 것이다. 

하지만 현업에서 DB 중심적 프로그래밍을 하다보면 꼭 마주하는 녀석일 것이다. 

왜냐혀면 참조형식에는 Null이라는 녀석이 있는데 C#의 값형식에는 Null이 없기 때문이다. 

Nullable 형식은 System.Nullable<T> 구조체의 인스턴스이다. 

Nullable 형식은 값 형식의 올바른 값 범위뿐 아니라 null 값도 나타낼 수 있도록 한다.

예를 들어 Nullable<Int32>에는 -2147483648에서 2147483647까지의 모든 값을 할당하거나 null 값을 할당할 수 있다.

숫자 및 부울 형식에 null 값을 할당할 수 있는 기능은 특히 값이 할당되지 않을 수 있는 데이터베이스 및 기타 데이터 형식을 다룰 때 유용하다.

1
2
3
4
5
6
7
8
9
10
using System;
 
public class SampleClass{
    public Nullable<int> num;
 
    public static void Main(){
        SampleClass sample = new SampleClass();
        Console.WriteLine("Nullable<int> : " + sample.num);
    }
}


소스를 간단하게 설명하자면 num 이라는 녀석을 초기화 하지 않고 출력했을 때 sample.num가 어떻게 나오는지 알아 보기 위함 이다. 

그렇다면 int형은 어떻게 나온까???

sample.num2를 보면 알겠지만 초기화를 하지 않았지만 0이 나온다. 기본적으로 값 형식은 자료형의 기본 디폴트 값을 내부적으로 초기화 하는 것이다. 


Nullable<T>의 특징

1. Nullable 형식은 null 값을 할당할 수 있는 값 형식 변수를 나타낸다.

참조 형식을 기반으로 nullable 형식을 만들 수는 없고, 참조 형식에서는 이미 null 값을 지원한다.

2. T? 구문은 Nullable<T>의 축약형이고, 여기서 T는 값 형식입니다. 이러한 두 가지 형태는 서로 바꿔 사용할 수 있다.


3. Nullable 형식에는 일반 값 형식과 같은 방법으로 값을 할당한다.

예를 들면 int? x = 10;(Nullable<int> x = 10;) 또는 double? d = 4.108(Nullable<double> d = 4.108)과 같습니다.             Nullable 형식은 null: int? x = null(Nullable<int> x = null) 값을 할당할 수도 있습니다.

4. Nullable<T>.GetValueOrDefault 메서드를 사용하여 할당된 값을 반환하거나 값이 null인 경우 값 형식의 기본값을 반환한다.

5. HasValue 및 Value 읽기 전용 속성이고 Null인지 확인하거나 값을 반환한다.(예제 if(x.HasValue) j = x.Value; 참조)

5.1 HasValue 속성은 변수에 값이 포함되어 있을 경우 true를 반환하고, 변수가 null이면 false를 반환한다.

5.2 할당된 값이 있으면 Value 속성은 값을 반활할 수 있다. 그렇지 않으면 System.InvalidOperationException이             throw된다.

5.3 HasValue의 기본값은 false입니다. Value 속성에는 기본값이 없다.

5.4 ==, != 연산자를 Nullable 형식으로 사용할 수도 있다(예제 if (x != null) y = x; 참조)

6. ?? 연산자를 사용하여 현재 값이 null인 nullable 형식을 nullable이 아닌 형식에 할당할 때 적용될 기본값을 할당한다. 

예를 들면 int? x = null; int y = x ?? -1;과 같다.

7. 중첩된 nullable 형식은 허용되지 않는다. Nullable<Nullable<int>> n;과 같은 줄은 컴파일되지 않는다.


사용시 주의점

명시적으로 값 형식을 변환하는 경우 문제가 있을 수 있다. 
총 3가지의 명시적 변환이 가능하지만 주의해야 할 점이 있다. 

1
2
3
4
5
int? n = null;
 
int m1 = n;      // A
int m2 = (int)n;   // B
int m3 = n.Value;  // C

// A : 컴파일이 되지 않는다. 

// B : 컴파일은 된다. 하지만 대입하는 순간 Exception발생 (n이 null이기 때문에 int형식으로 대입 되지 않는다.)

// C : 컴파일은 된다. 하지만 대입하는 순간 Exception발생 (n이 null이기 때문에 int형식으로 대입 되지 않는다.)


명시적인 변환에서는 HasValue를 확인하고 변환을 해주는 것이 좋을 것 같다.


이상 Nullable 사용법니다. 

끝....