nullable 값 형식은 기본 값 형식 T T? 의 모든 값과 추가 null 값을 나타냅니다.
bool? 변수에는 다음 세가지 값중 하나를 할당할 수 있습니다.
true, flase, null 기본값 형식T는 null 허용 값 형식 자체일 수 없습니다.
Null 허용 값 형식은 제네릭 System.Nullable<T> 구조체의 인스턴스 입니다.
서로 교환 가능한 형식인 Nullable<T> 또는 T? 중 하나에서 기본값 형식 T의 null 허용 값 형식을 참조할 수 있습니다.
기본 값 형식의 정의되지 않은 값을 표시해야 하는 경우 일반적으로 null 허용 값 형식을 사용합니다.
예를 들어 부울 변수는 true 또는 false만 가능합니다.
그러나 일부 애플리케이션에서는 변수 값이 정의되지 않았거나 누락될 수 없습니다.
예를 들어 데이터 베이스 필드는 true 또는 false를 포함하거나 아무 값도 없을 수 있습니다.
이러한 시나리오에서 bool? 형식을 사용할 수 있습니다.
선언 및 할당
값 형식이 암시적으로 해당 null 허용 값 형식으로 변환될 수 있기 때문에 기본 값 형식에서와 마찬가지로 null 허용 값 형식의 변수에 값을 할당할 수 있습니다.
double? pi = 3.14;
char? letter = 'a';
int m2 = 10;
int? m = m2;
bool? flag = null;
// An array of a nullable value type:
int?[] arr = new int?[10];
Null 허용 값 형식의 인스턴스 검사
형식 패턴이 있는 연산자 is를 사용하여 nullable 값 형식의 인스턴스를 검사하고 기본 형식 null의 값을 검색할 수 있습니다.
int? a = 42;
if (a is int valueOfA)
{
Console.WriteLine($"a is {valueOfA}");
}
else
{
Console.WriteLine("a does not have a value");
}
// Output:
// a is 42
항상 다음 읽기 전용 속성을 사용하여 null 허용 값 형식 변수의 값을 검사하고 가져올 수 있습니다.
- Nullable<T>.HasValue은 null 허용 값 형식의 인스턴스에 해당 기본 형식의 값이 있는지 여부를 나타냅니다.
- Nullable<T>.Value는 HasValue가 true인 경우 기본 형식의 값을 가져옵니다. HasValue가 false인 경우 Value 속성은 InvalidOperationException을 throw합니다.
int? b = 10;
if (b.HasValue)
{
Console.WriteLine($"b is {b.Value}");
}
else
{
Console.WriteLine("b does not have a value");
}
// Output:
// b is 10
int? c = 7;
if (c != null)
{
Console.WriteLine($"c is {c.Value}");
}
else
{
Console.WriteLine("c does not have a value");
}
// Output:
// c is 7
nullable 값 형식에서 기본 형식으로 변환
Null 허용 값 형식의 값을 null 을 허용하지 않는 값 형식 변수에 할당하려는 경우 null 대신 할당할 값을 지정해야 할 수 있습니다.
null 병합 연산자 ?? 를 사용하여 이 작업을 수행 할 수 있습니다.
int? a = 28;
int b = a ?? -1;
Console.WriteLine($"b is {b}"); // output: b is 28
int? c = null;
int d = c ?? -1;
Console.WriteLine($"d is {d}"); // output: d is -1
null 대신 기본 값 형식의 기본값을 사용하려면 Nullable<T>.GetValueOrDefualt() 메서드를 사용합니다.
다음 예제와 같이 null 허용 값 형식을 null을 허용하지 않는 형식으로 명시적 캐스팅할 수도 있습니다.
int? n = null;
//int m1 = n; // Doesn't compile
int n2 = (int)n; // Compiles, but throws an exception if n is null
런타임 시 nullable 값 형식의 값이 null 인경우 명시적 캐스트는 InvalidOperationException을 throw합니다.
null을 허용하지 않는 값 형식 T는 해당 null 허용 값 형식 T?로 암시적으로 변환될 수 있습니다.
리프트 연산자
미리 정의된 단항 및 이항 연산자 또는 값 형식 T에서 지원하는 오버로드된 연산자는 해당 null 허용 값 형식 T?에서도 지원합니다.
리프트 연산자라고도 하는 이러한 연산자는 하나 또는 두 개의 피연산자가 null인 경우 null 값을 생성하거, 그렇지 않으면 연산자는 포함된 피연산자 값을 사용하여 결과를 계산합니다.
int? a = 10;
int? b = null;
int? c = 10;
a++; // a is 11
a = a * c; // a is 110
a = a + b; // a is null
비교연산자 <의 경우 , <=, >, >= 피연산자 중 하나 또는 둘다 null인 경우 결과는 false 이고 그렇지 않으면 피연산자의 포함된 값이 비교됩니다.
int? a = 10;
Console.WriteLine($"{a} >= null is {a >= null}");
Console.WriteLine($"{a} < null is {a < null}");
Console.WriteLine($"{a} == null is {a == null}");
// Output:
// 10 >= null is False
// 10 < null is False
// 10 == null is False
int? b = null;
int? c = null;
Console.WriteLine($"null >= null is {b >= c}");
Console.WriteLine($"null == null is {b == c}");
// Output:
// null >= null is False
// null == null is True
같음 연산자 == 의 경우 두 피연산자가 모두 null이면 결과는 true 피연산자중 하나만 null이면 결과가 false이고 그렇지 않으면 피연산자의 포함된 값이 비교됩니다.
같지 않음 연산자 !=의 경우 두 피연산자가 모두 null 이면 결과는 false 피연산자 null 중하나만 있으면 결과가 true이고, 그렇지 않으면 피연산자의 포함된 값이 비교됩니다.
두 값 형식 사이에 사용자 정의 변환이 있는 경우 해당 null 허용 값 형식 사이에도 같은 변환을 사용할 수 있습니다.
boxing 및 unboxing
Null 허용 값 형식 T? 의 인스턴스는 다음과 같이 box됩니다.
- HasValue가 false를 반환하는 경우 Null 참조가 생성됩니다.
- HasValue가 true를 반환하는 경우 Nullable<T>의 인스턴스가 아닌 기본 값 형식 T의 인스턴스가 box됩니다.
int a = 41;
object aBoxed = a;
int? aNullable = (int?)aBoxed;
Console.WriteLine($"Value of aNullable: {aNullable}");
object aNullableBoxed = aNullable;
if (aNullableBoxed is int valueOfA)
{
Console.WriteLine($"aNullableBoxed is boxed int: {valueOfA}");
}
// Output:
// Value of aNullable: 41
// aNullableBoxed is boxed int: 41
Null 허용 값 형식 식별 방법
System.Type 인스턴스가 구성된 null 허용 값 형식(지정된 형식 매개변수 T가 포함된 System.Nullable<T> 형식)을 나타내는지 확인하는 방법을 보여준다.
Console.WriteLine($"int? is {(IsNullable(typeof(int?)) ? "nullable" : "non nullable")} value type");
Console.WriteLine($"int is {(IsNullable(typeof(int)) ? "nullable" : "non-nullable")} value type");
bool IsNullable(Type type) => Nullable.GetUnderlyingType(type) != null;
// Output:
// int? is nullable value type
// int is non-nullable value type
예제에서와 같이 typeof 연산자를 사용하여 System.Type 인스턴스를 만듭니다.
인스턴스가 있는지 nullable 값 형식인지 여부를 확인하려는 경우 위의 코드로 테스트되도록 Type 인스턴스를 가져오는데 Object.GetType 메서드를 사용하지 마세요.
Nullable 값 형식의 인스턴스에서 Object.GetType 메서드를 호출하는 경우 인스턴스는 Object로 boxing됩니다.
Null허용값 형식의 Null이 아닌 인스턴스의 boxing과 동일하며, GetType는 null 허용값 형식의 기본 형식을 나타내는 Type 인스턴스를 반환합니다.
int? a = 17;
Type typeOfA = a.GetType();
Console.WriteLine(typeOfA.FullName);
// Output:
// System.Int32
그리고 인스턴스가 null 허용값 형식인지 여부를 확인하는데 is 연산자를 사용하지 마세요.
다음 예제에서와 같이 null 허용 값 형식의 인스턴스와 isㅇㄴ산자르 사용하는 해당 형식 인스턴스를 구분할 수 없습니다.
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?
'C#' 카테고리의 다른 글
C# Value Type : 값 형식 - 구조체 : Struct (0) | 2023.01.18 |
---|---|
C# Value Type : 값 형식 - 열거형 (0) | 2023.01.17 |
C# Value Type : 값 형식 - char (0) | 2023.01.17 |
C# Value Type : 값 형식 - bool (0) | 2023.01.16 |
C# Value Type : 값 형식 - 부동 소수점 숫자 형식 (2) | 2023.01.16 |