여기에는 두 가지 문제가 있습니다. 1) 유형이 널 입력 가능 여부를 테스트; 2) 객체가 nullable Type을 나타내는 지 테스트
문제 1 (유형 테스트)의 경우 내 시스템에서 사용한 솔루션은 다음과 같습니다. TypeIsNullable-check solution
문제 2 (객체 테스트)의 경우 위의 Dean Chalk 솔루션은 값 유형에 대해 작동하지만 <T> 과부하를 사용하면 항상 false를 반환하므로 참조 유형에 대해서는 작동하지 않습니다. 참조 유형은 본질적으로 널 입력 가능하므로 참조 유형 테스트는 항상 true를 리턴해야합니다. 이러한 의미에 대한 설명은 아래의 "널링 가능성"정보를 참조하십시오. 따라서 Dean의 접근 방식에 대한 수정 사항은 다음과 같습니다.
public static bool IsObjectNullable<T>(T obj)
{
// If the parameter-Type is a reference type, or if the parameter is null, then the object is always nullable
if (!typeof(T).IsValueType || obj == null)
return true;
// Since the object passed is a ValueType, and it is not null, it cannot be a nullable object
return false;
}
public static bool IsObjectNullable<T>(T? obj) where T : struct
{
// Always return true, since the object-type passed is guaranteed by the compiler to always be nullable
return true;
}
위의 솔루션에 대한 클라이언트 테스트 코드에 대한 수정 사항은 다음과 같습니다.
int a = 123;
int? b = null;
object c = new object();
object d = null;
int? e = 456;
var f = (int?)789;
string g = "something";
bool isnullable = IsObjectNullable(a); // false
isnullable = IsObjectNullable(b); // true
isnullable = IsObjectNullable(c); // true
isnullable = IsObjectNullable(d); // true
isnullable = IsObjectNullable(e); // true
isnullable = IsObjectNullable(f); // true
isnullable = IsObjectNullable(g); // true
IsObjectNullable <T> (T t)에서 Dean의 접근 방식을 수정 한 이유는 원래 접근 방식이 항상 참조 유형에 대해 false를 반환했기 때문입니다. IsObjectNullable과 같은 메소드는 참조 유형 값을 처리 할 수 있어야하고 모든 참조 유형이 본질적으로 널 입력 가능하므로 참조 유형 또는 널이 전달되면 메소드는 항상 true를 리턴해야합니다.
위의 두 가지 방법을 다음과 같은 단일 방법으로 대체하여 동일한 결과를 얻을 수 있습니다.
public static bool IsObjectNullable<T>(T obj)
{
Type argType = typeof(T);
if (!argType.IsValueType || obj == null)
return true;
return argType.IsGenericType && argType.GetGenericTypeDefinition() == typeof(Nullable<>);
}
그러나이 마지막 단일 방법 접근법의 문제점은 Nullable <T> 매개 변수를 사용할 때 성능이 저하된다는 것입니다. IsObjectNullable 호출에 Nullable <T> 유형 매개 변수가 사용될 때 컴파일러가 이전에 표시된 두 번째 메서드 오버로드를 선택할 수 있도록 허용하는 것보다이 단일 메서드의 마지막 행을 실행하는 데 훨씬 더 많은 프로세서 시간이 걸립니다. 따라서 최적의 솔루션은 여기에 설명 된 2 가지 방법을 사용하는 것입니다.
주의 사항 :이 방법은 예제에 표시된 것처럼 원본 객체 참조 또는 정확한 사본을 사용하여 호출 된 경우에만 안정적으로 작동합니다. 그러나 nullable 객체가 원래 Nullable <> 형식으로 남아 있지 않고 다른 유형 (예 : 객체 등)으로 박스 화 된 경우이 메서드는 안정적으로 작동하지 않습니다. 이 메소드를 호출하는 코드가 원래의 언 박스 (unboxed) 객체 참조 또는 정확한 사본을 사용하지 않는 경우이 메소드를 사용하여 객체의 null 가능성을 안정적으로 결정할 수 없습니다.
대부분의 코딩 시나리오에서, Null 허용 여부를 결정하려면 대신 참조가 아닌 원래 객체의 Type 테스트에 의존해야합니다 (예 : 코드는 Null 허용 여부를 결정하기 위해 객체의 원래 유형에 액세스해야합니다) 이러한보다 일반적인 경우 IsTypeNullable (링크 참조)은 Null 허용 여부를 결정하는 신뢰할 수있는 방법입니다.
PS- "널링 가능성"정보
별도의 게시물에서 작성한 Null 허용 여부에 대한 설명을 반복해야 하며이 주제를 올바르게 처리하는 데 직접 적용됩니다. 즉, 여기서 논의의 초점은 객체가 일반 Nullable 유형인지 확인하는 것이 아니라 유형의 객체에 null 값을 할당 할 수 있는지 여부를 확인하는 방법이어야한다고 생각합니다. 다시 말해, 객체 유형이 널 입력 가능 여부가 아닌 널 입력 가능 여부를 결정해야한다고 생각합니다. 차이점은 의미론, 즉 무효 성을 결정하기위한 실질적인 이유에 있습니다.
런타임까지 알려지지 않은 유형의 객체 (웹 서비스, 원격 호출, 데이터베이스, 피드 등)를 사용하는 시스템에서 일반적인 요구 사항은 객체에 null을 할당 할 수 있는지 또는 객체에 포함될 수 있는지 여부를 결정하는 것입니다. null 널 입력 가능하지 않은 유형에서 이러한 조작을 수행하면 성능 및 코딩 요구 사항 모두에서 매우 비싼 오류 (일반적으로 예외)가 발생할 수 있습니다. 이러한 문제를 사전에 피하는 것이 가장 선호되는 접근 방식을 취하려면 임의 유형의 오브젝트가 널을 포함 할 수 있는지 판별해야합니다. 즉, 일반적으로 '널링 가능'여부입니다.
매우 실용적이고 일반적인 의미에서 .NET 용어의 Null 허용 여부는 반드시 개체 유형이 Nullable 형식임을 의미하지는 않습니다. 실제로 많은 경우에 객체는 참조 유형을 가지며 널값을 포함 할 수 있으므로 모두 널 입력 가능합니다. 이들 중 어느 것도 널 입력 가능 유형이 없습니다. 따라서 대부분의 시나리오에서 실제적인 목적을 위해서는 Nullable의 구현 종속 개념과 비교하여 nullable의 일반적인 개념에 대해 테스트를 수행해야합니다. 따라서 우리는 .NET Nullable 유형에만 중점을 두지 말고 일반적인 Null 허용 개념에 초점을 맞추는 과정에서 요구 사항과 동작에 대한 이해를 통합하십시오.