Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if an object is nullable?

Tags:

c#

.net

nullable

People also ask

How check object is null or not in C#?

C# | IsNullOrEmpty() Method In C#, IsNullOrEmpty() is a string method. It is used to check whether the specified string is null or an Empty string. A string will be null if it has not been assigned a value. A string will be empty if it is assigned “” or String.

What is a nullable type in C#?

The Nullable type allows you to assign a null value to a variable. Nullable types introduced in C#2.0 can only work with Value Type, not with Reference Type. The nullable types for Reference Type is introduced later in C# 8.0 in 2019 so that we can explicitly define if a reference type can or can not hold a null value.

How do you check if a Boolean is nullable?

(a ?: b) is equivalent to (if (a != null) a else b). So checking a nullable Boolean to true can be shortly done with the elvis operator like that: if ( a ?: false ) { ... } else { .... }

How do you define a nullable?

In this article A nullable type is a value type that you extend so that it takes the typical range of values for that type and also a null value. For example, a nullable of Int32 , also denoted as Nullable<Int32>, can be assigned any value from -2147483648 to 2147483647, or it can be assigned a null value.


There are two types of nullable - Nullable<T> and reference-type.

Jon has corrected me that it is hard to get type if boxed, but you can with generics: - so how about below. This is actually testing type T, but using the obj parameter purely for generic type inference (to make it easy to call) - it would work almost identically without the obj param, though.

static bool IsNullable<T>(T obj)
{
    if (obj == null) return true; // obvious
    Type type = typeof(T);
    if (!type.IsValueType) return true; // ref-type
    if (Nullable.GetUnderlyingType(type) != null) return true; // Nullable<T>
    return false; // value-type
}

But this won't work so well if you have already boxed the value to an object variable.

Microsoft documentation: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/nullable-types/how-to-identify-a-nullable-type


There is a very simple solution using method overloads

http://deanchalk.com/is-it-nullable/

excerpt:

public static class ValueTypeHelper
{
    public static bool IsNullable<T>(T t) { return false; }
    public static bool IsNullable<T>(T? t) where T : struct { return true; }
}

then

static void Main(string[] args)
{
    int a = 123;
    int? b = null;
    object c = new object();
    object d = null;
    int? e = 456;
    var f = (int?)789;
    bool result1 = ValueTypeHelper.IsNullable(a); // false
    bool result2 = ValueTypeHelper.IsNullable(b); // true
    bool result3 = ValueTypeHelper.IsNullable(c); // false
    bool result4 = ValueTypeHelper.IsNullable(d); // false
    bool result5 = ValueTypeHelper.IsNullable(e); // true
    bool result6 = ValueTypeHelper.IsNullable(f); // true

This works for me and seems simple:

static bool IsNullable<T>(T obj)
{
    return default(T) == null;
}

For value types:

static bool IsNullableValueType<T>(T obj)
{
    return default(T) == null && typeof(T).BaseType != null && "ValueType".Equals(typeof(T).BaseType.Name);
}

The question of "How to check if a type is nullable?" is actually "How to check if a type is Nullable<>?", which can be generalized to "How to check if a type is a constructed type of some generic type?", so that it not only answers the question "Is Nullable<int> a Nullable<>?", but also "Is List<int> a List<>?".

Most of the provided solution use the Nullable.GetUnderlyingType() method, which will obviously only work with the case of Nullable<>. I did not see the general reflective solution that will work with any generic type, so I decided to add it here for posterity, even though this question has already been answered long ago.

To check if a type is some form of Nullable<> using reflection, you first have to convert your constructed generic type, for example Nullable<int>, into the generic type definition, Nullable<>. You can do that by using the GetGenericTypeDefinition() method of the Type class. You can then compare the resulting type to Nullable<>:

Type typeToTest = typeof(Nullable<int>);
bool isNullable = typeToTest.GetGenericTypeDefinition() == typeof(Nullable<>);
// isNullable == true

The same can be applied to any generic type:

Type typeToTest = typeof(List<int>);
bool isList = typeToTest.GetGenericTypeDefinition() == typeof(List<>);
// isList == true

Several types may seem the same, but a different number of type arguments means it's a completely different type.

Type typeToTest = typeof(Action<DateTime, float>);
bool isAction1 = typeToTest.GetGenericTypeDefinition() == typeof(Action<>);
bool isAction2 = typeToTest.GetGenericTypeDefinition() == typeof(Action<,>);
bool isAction3 = typeToTest.GetGenericTypeDefinition() == typeof(Action<,,>);
// isAction1 == false
// isAction2 == true
// isAction3 == false

Since Type object are instantiated once per type, you can check for reference equality between them. So if you want to check if two objects are of the same generic type definition, you can write:

var listOfInts = new List<int>();
var listOfStrings = new List<string>();

bool areSameGenericType =
    listOfInts.GetType().GetGenericTypeDefinition() ==
    listOfStrings.GetType().GetGenericTypeDefinition();
// areSameGenericType == true

If you'd like to check if an object is nullable, rather than a Type, then you can use the above technique together with Marc Gravell's solution to create a rather simple method:

static bool IsNullable<T>(T obj)
{
    if (!typeof(T).IsGenericType)
        return false;

    return typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>);
}