Favicon

Nullable value types

Peponi11/20/20243m

C#
SyntaxTypeValue?

1. Introduction

기본적으로 값 형식은 항상 해당 타입에 맞는 값을 가져야 하고, null을 가질 수 없다. 값 형식null 값이 필요한 경우 ?를 붙여 null 허용 값 형식으로 선언할 수 있다.

null 허용 값 형식System.Nullable<T> 구조체의 인스턴스이며, 조건에 따라 System.T 형식으로 돌아올 수 있다.

2. T? 선언 및 사용

아래와 같이 T? 형식을 선언 및 사용할 수 있다.

int X = 1;
double? Y = default;
 
Console.WriteLine(X);   // 1
Console.WriteLine(Y);   // null

3. T? 형식 및 인스턴스 검사

아래와 같이 T? 형식 검사를 수행할 수 있다.

if(Nullable.GetUnderlyingType(typeof(T?)))
{
    // Processing...
}

아래와 같이 형식 검사를 수행하면 안된다. 아래는 잘못된 두 가지 방법에 대한 MSDN 예제이다.

int? a = 17;
Type typeOfA = a.GetType();
Console.WriteLine(typeOfA.FullName);
    
/* output:
System.Int32
*/
int? a = 14;
if (a is int)
{
    Console.WriteLine("int? instance is compatible with int");
}
 
int b = 17;
if (b is int?)
{
    Console.WriteLine("int instance is compatible with int?");
}
 
/* output:
int? instance is compatible with int
int instance is compatible with int?
*/

T?의 인스턴스 검사 방법은 아래와 같다.

int? A = 1;
if(A is int valueA)
{
    // Processing...
}
 
int? B = 2;
if(B.HasValue)
{
    // Processing...
}
 
int? C = 3;
if(C != null)
{
    // Processing...
}

4. T? -> T 형식 변환

아래와 같은 방법으로 T? 형식을 T 형식으로 변환할 수 있다.

int? A = 1;
int B = A ?? -999;
 
int? C = null;
int D = C ?? -999;
 
Console.WriteLine(B);           // 1
Console.WriteLine(D);           // -999;
int? A = 1;
int B = A.GetValueOrDefault();  // 1
 
int? C = null;
int D = C.GetValueOrDefault();  // 0
// 명시적 캐스팅 가능
int? A = 1;
int B = (int)A;
 
// null을 변환하려 하는 경우 exception 발생 
A = null;
B = (int)A;     // System.InvalidOperationException: 'Nullable object must have a value.'

5. T? 연산

T? 연산은 T와 동일하게 지원된다. 다만 연산자가 리프트 연산자로 적용되어 null에 대한 규칙이 추가로 적용된다.

int? A = 1;
int? B = 5;
int? C = null;
int? D = null;
 
Console.WriteLine(A + B);         // 6
Console.WriteLine(A + C);        // null
Console.WriteLine(A > null);     // False
Console.WriteLine(A <= null);   // False
Console.WriteLine(C > D);        // False
Console.WriteLine(C == D);      // True

6. 참조 자료