Section 38.6: Nullable<T> 인자의 기반 (underlying) 타입에 대한 효과적인 사용법
모든 nullable 타입은 generic 타입이다. 또한 모든 nullable 타입은 값 (value) 타입이다.
역주: C# 8.0부터는 nullable reference 타입에 대한 새로운 개념이 추가되었습니다. Microsoft 문서 를 참조하세요.
Reflection 이나 코드 자동생성 목적의 코드를 작성할 때, Nullable.GetUnderlyingType
메소드의 결과를 효과적으로 사용할 수 있는 몇가지 기법을 아래의 코드에서 소개하고 있다:
public static class TypesHelper {
public static bool IsNullable(this Type type) {
Type underlyingType;
return IsNullable(type, out underlyingType);
}
public static bool IsNullable(this Type type, out Type underlyingType) {
underlyingType = Nullable.GetUnderlyingType(type);
return underlyingType != null;
}
public static Type GetNullable(Type type) {
Type underlyingType;
return IsNullable(type, out underlyingType) ? type : NullableTypesCache.Get(type);
}
public static bool IsExactOrNullable(this Type type, Func < Type, bool > predicate) {
Type underlyingType;
if (IsNullable(type, out underlyingType))
return IsExactOrNullable(underlyingType, predicate);
return predicate(type);
}
public static bool IsExactOrNullable < T > (this Type type)
where T: struct {
return IsExactOrNullable(type, t => Equals(t, typeof (T)));
}
}
사용 예제:
Type type = typeof (int).GetNullable();
Console.WriteLine(type.ToString());
if (type.IsNullable())
Console.WriteLine("Type is nullable.");
Type underlyingType;
if (type.IsNullable(out underlyingType))
Console.WriteLine("The underlying type is " + underlyingType.Name + ".");
if (type.IsExactOrNullable < int > ())
Console.WriteLine("Type is either exact or nullable Int32.");
if (!type.IsExactOrNullable(t => t.IsEnum))
Console.WriteLine("Type is neither exact nor nullable enum.");
출력 결과:
System.Nullable`1[System.Int32]
Type is nullable.
The underlying type is Int32.
Type is either exact or nullable Int32.
Type is neither exact nor nullable enum.
참고로, NullableTypesCache
는 아래와 같이 선언되어 있다:
static class NullableTypesCache {
readonly static ConcurrentDictionary < Type, Type > cache = new ConcurrentDictionary < Type,
Type > ();
static NullableTypesCache() {
cache.TryAdd(typeof (byte), typeof (Nullable < byte > ));
cache.TryAdd(typeof (short), typeof (Nullable < short > ));
cache.TryAdd(typeof (int), typeof (Nullable < int > ));
cache.TryAdd(typeof (long), typeof (Nullable < long > ));
cache.TryAdd(typeof (float), typeof (Nullable < float > ));
cache.TryAdd(typeof (double), typeof (Nullable < double > ));
cache.TryAdd(typeof (decimal), typeof (Nullable < decimal > ));
cache.TryAdd(typeof (sbyte), typeof (Nullable < sbyte > ));
cache.TryAdd(typeof (ushort), typeof (Nullable < ushort > ));
cache.TryAdd(typeof (uint), typeof (Nullable < uint > ));
cache.TryAdd(typeof (ulong), typeof (Nullable < ulong > ));
//...
}
readonly static Type NullableBase = typeof (Nullable < > );
internal static Type Get(Type type) {
// 호출 비용이 많이 드는 MakeGenericType 메소드 호출을 지양한다
return cache.GetOrAdd(type, t => NullableBase.MakeGenericType(t));
}
}
본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.
[출처] https://books.goalkicker.com/CSharpBook/
'번역 > C# Notes for Professionals' 카테고리의 다른 글
39: 생성자와 종료자 (Finalizer) (0) | 2022.02.09 |
---|---|
38.7: 제네릭 타입 인자가 nullable 타입인지 확인하기 (0) | 2022.02.09 |
38.5: Nullable 타입의 기본값은 null 이다 (0) | 2022.02.03 |
38.4: 기본 값을 지정하여 Nullable 타입이 가지고 있는 값 가져오기 (0) | 2022.01.26 |
38.3: Nullable 타입이 가지고 있는 값 얻어오기 (0) | 2022.01.21 |