How to check if an object is nullable?

C#.NetNullable

C# Problem Overview


How do I check if a given object is nullable in other words how to implement the following method...

bool IsNullableValueType(object o)
{
    ...
}

I am looking for nullable value types. I didn't have reference types in mind.

//Note: This is just a sample. The code has been simplified 
//to fit in a post.

public class BoolContainer
{
	bool? myBool = true;
}

var bc = new BoolContainer();

const BindingFlags bindingFlags = BindingFlags.Public
						| BindingFlags.NonPublic
						| BindingFlags.Instance
						;


object obj;
object o = (object)bc;

foreach (var fieldInfo in o.GetType().GetFields(bindingFlags))
{
	obj = (object)fieldInfo.GetValue(o);
}

obj now refers to an object of type bool (System.Boolean) with value equal to true. What I really wanted was an object of type Nullable<bool>

So now as a work around I decided to check if o is nullable and create a nullable wrapper around obj.

C# Solutions


Solution 1 - C#

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 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 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

Solution 2 - C#

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

Solution 3 - C#

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);
}

Solution 4 - C#

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<>);
}

Solution 5 - C#

Well, you could use:

return !(o is ValueType);

... but an object itself isn't nullable or otherwise - a type is. How were you planning on using this?

Solution 6 - C#

The simplest solution I came up with is to implement Microsoft's solution (How to: Identify a Nullable Type (C# Programming Guide)) as an extension method:

public static bool IsNullable(this Type type)
{
    return Nullable.GetUnderlyingType(type) != null;
}

This can then be called like so:

bool isNullable = typeof(int).IsNullable();

This also seems a logical way to access IsNullable() because it fits in with all of the other IsXxxx() methods of the Type class.

Solution 7 - C#

The simplest way I can figure out is:

public bool IsNullable(object obj)
{
    Type t = obj.GetType();
    return t.IsGenericType 
        && t.GetGenericTypeDefinition() == typeof(Nullable<>);
}

Solution 8 - C#

There are two issues here: 1) testing to see whether a Type is nullable; and 2) testing to see whether an object represents a nullable Type.

For issue 1 (testing a Type), here's a solution I've used in my own systems: TypeIsNullable-check solution

For issue 2 (testing an object), Dean Chalk's solution above works for value types, but it doesn't work for reference types, since using the <T> overload always returns false. Since reference types are inherently nullable, testing a reference type should always return true. Please see the note [About "nullability"] below for an explanation of these semantics. Thus, here's my modification to Dean's approach:

    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;
    }

And here's my modification to the client-test code for the above solution:

    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

The reason I've modified Dean's approach in IsObjectNullable<T>(T t) is that his original approach always returned false for a reference type. Since a method like IsObjectNullable should be able to handle reference-type values and since all reference types are inherently nullable, then if either a reference type or a null is passed, the method should always return true.

The above two methods could be replaced with the following single method and achieve the same output:

    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<>);
    }

However, the problem with this last, single-method approach is that performance suffers when a Nullable<T> parameter is used. It takes much more processor time to execute the last line of this single method than it does to allow the compiler to choose the second method overload shown previously when a Nullable<T>-type parameter is used in the IsObjectNullable call. Therefore, the optimum solution is to use the two-method approach illustrated here.

CAVEAT: This method works reliably only if called using the original object reference or an exact copy, as shown in the examples. However, if a nullable object is boxed to another Type (such as object, etc.) instead of remaining in its original Nullable<> form, this method will not work reliably. If the code calling this method is not using the original, unboxed object reference or an exact copy, it cannot reliably determine the object's nullability using this method.

In most coding scenarios, to determine nullability one must instead rely on testing the original object's Type, not its reference (e.g., code must have access to the object's original Type to determine nullability). In these more common cases, IsTypeNullable (see link) is a reliable method of determining nullability.

P.S. - About "nullability"

I should repeat a statement about nullability I made in a separate post, which applies directly to properly addressing this topic. That is, I believe the focus of the discussion here should not be how to check to see if an object is a generic Nullable type, but rather whether one can assign a value of null to an object of its type. In other words, I think we should be determining whether an object type is nullable, not whether it is Nullable. The difference is in semantics, namely the practical reasons for determining nullability, which is usually all that matters.

In a system using objects with types possibly unknown until run-time (web services, remote calls, databases, feeds, etc.), a common requirement is to determine whether a null can be assigned to the object, or whether the object might contain a null. Performing such operations on non-nullable types will likely produce errors, usually exceptions, which are very expensive both in terms of performance and coding requirements. To take the highly-preferred approach of proactively avoiding such problems, it is necessary to determine whether an object of an arbitrary Type is capable of containing a null; i.e., whether it is generally 'nullable'.

In a very practical and typical sense, nullability in .NET terms does not at all necessarily imply that an object's Type is a form of Nullable. In many cases in fact, objects have reference types, can contain a null value, and thus are all nullable; none of these have a Nullable type. Therefore, for practical purposes in most scenarios, testing should be done for the general concept of nullability, vs. the implementation-dependent concept of Nullable. So we should not be hung up by focusing solely on the .NET Nullable type but rather incorporate our understanding of its requirements and behavior in the process of focusing on the general, practical concept of nullability.

Solution 9 - C#

Be carefull, when boxing a nullable type (Nullable<int> or int? for instance) :

int? nullValue = null;
object boxedNullValue = (object)nullValue;
Debug.Assert(boxedNullValue == null);

int? value = 10;
object boxedValue = (object)value;
Debug.Assert( boxedValue.GetType() == typeof(int))

It becomes a true reference type, so you lose the fact it was nullable.

Solution 10 - C#

Maybe a little bit off topic, but still some interesting information. I find a lot of people that use Nullable.GetUnderlyingType() != null to identity if a type is nullable. This obviously works, but Microsoft advices the following type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>) (see http://msdn.microsoft.com/en-us/library/ms366789.aspx).

I looked at this from a performance side of view. The conclusion of the test (one million attempts) below is that when a type is a nullable, the Microsoft option delivers the best performance.

Nullable.GetUnderlyingType(): 1335ms (3 times slower)

GetGenericTypeDefinition() == typeof(Nullable<>): 500ms

I know that we are talking about a small amount of time, but everybody loves to tweak the milliseconds :-)! So if you're boss wants you to reduce some milliseconds then this is your saviour...

/// <summary>Method for testing the performance of several options to determine if a type is     nullable</summary>
[TestMethod]
public void IdentityNullablePerformanceTest()
{
    int attempts = 1000000;

    Type nullableType = typeof(Nullable<int>);

    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    for (int attemptIndex = 0; attemptIndex < attempts; attemptIndex++)
    {
        Assert.IsTrue(Nullable.GetUnderlyingType(nullableType) != null, "Expected to be a nullable"); 
    }

    Console.WriteLine("Nullable.GetUnderlyingType(): {0} ms", stopwatch.ElapsedMilliseconds);
        
    stopwatch.Restart();

    for (int attemptIndex = 0; attemptIndex < attempts; attemptIndex++)
   {
       Assert.IsTrue(nullableType.IsGenericType && nullableType.GetGenericTypeDefinition() == typeof(Nullable<>), "Expected to be a nullable");
   }

   Console.WriteLine("GetGenericTypeDefinition() == typeof(Nullable<>): {0} ms", stopwatch.ElapsedMilliseconds);
   stopwatch.Stop();
}

Solution 11 - C#

I think the ones using Microsoft's suggested testing against IsGenericType are good, but in the code for GetUnderlyingType, Microsoft uses an additional test to make sure you didn't pass in the generic type definition Nullable<>:

 public static bool IsNullableType(this Type nullableType) =>
    // instantiated generic type only                
    nullableType.IsGenericType &&
    !nullableType.IsGenericTypeDefinition &&
    Object.ReferenceEquals(nullableType.GetGenericTypeDefinition(), typeof(Nullable<>));

Solution 12 - C#

This version:

  • caching results is faster,
  • does not require unnecessary variables, like Method(T obj)
  • NOT COMPLICATED :),
  • just static generic class, that has one time computed fields

:

public static class IsNullable<T>
{
    private static readonly Type type = typeof(T);
    private static readonly bool is_nullable = type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
    public static bool Result { get { return is_nullable; } }
}

bool is_nullable = IsNullable<int?>.Result;

Solution 13 - C#

Here is what I came up with, as everything else seemed to fail - at least on the PLC - Portable Class Library / .NET Core with >= C# 6

Solution: Extend static methods for any Type T and Nullable<T> and use the fact that the static extension method, matching the underlying type is going to be invoked and takes precedence over the generic T extension-method.

For T:

public static partial class ObjectExtension
{
    public static bool IsNullable<T>(this T self)
    {
        return false;
    }
}

and for Nullable<T>

public static partial class NullableExtension
{
    public static bool IsNullable<T>(this Nullable<T> self) where T : struct
    {
        return true;
    }
}

Using Reflection and type.IsGenericType... did not work on my current set of .NET Runtimes. Nor did the MSDN Documentation help.

if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) {…}

In part because the Reflection API has been changed quite significantly in .NET Core.

Solution 14 - C#

a simple way to do this:

    public static bool IsNullable(this Type type)
    {
        if (type.IsValueType) return Activator.CreateInstance(type) == null;

        return true;
    }

these are my unit tests and all passed

    IsNullable_String_ShouldReturn_True
    IsNullable_Boolean_ShouldReturn_False
    IsNullable_Enum_ShouldReturn_Fasle
    IsNullable_Nullable_ShouldReturn_True
    IsNullable_Class_ShouldReturn_True
    IsNullable_Decimal_ShouldReturn_False
    IsNullable_Byte_ShouldReturn_False
    IsNullable_KeyValuePair_ShouldReturn_False

actual unit tests

    [TestMethod]
    public void IsNullable_String_ShouldReturn_True()
    {
        var typ = typeof(string);
        var result = typ.IsNullable();
        Assert.IsTrue(result);
    }

    [TestMethod]
    public void IsNullable_Boolean_ShouldReturn_False()
    {
        var typ = typeof(bool);
        var result = typ.IsNullable();
        Assert.IsFalse(result);
    }

    [TestMethod]
    public void IsNullable_Enum_ShouldReturn_Fasle()
    {
        var typ = typeof(System.GenericUriParserOptions);
        var result = typ.IsNullable();
        Assert.IsFalse(result);
    }

    [TestMethod]
    public void IsNullable_Nullable_ShouldReturn_True()
    {
        var typ = typeof(Nullable<bool>);
        var result = typ.IsNullable();
        Assert.IsTrue(result);
    }

    [TestMethod]
    public void IsNullable_Class_ShouldReturn_True()
    {
        var typ = typeof(TestPerson);
        var result = typ.IsNullable();
        Assert.IsTrue(result);
    }

    [TestMethod]
    public void IsNullable_Decimal_ShouldReturn_False()
    {
        var typ = typeof(decimal);
        var result = typ.IsNullable();
        Assert.IsFalse(result);
    }

    [TestMethod]
    public void IsNullable_Byte_ShouldReturn_False()
    {
        var typ = typeof(byte);
        var result = typ.IsNullable();
        Assert.IsFalse(result);
    }

    [TestMethod]
    public void IsNullable_KeyValuePair_ShouldReturn_False()
    {
        var typ = typeof(KeyValuePair<string, string>);
        var result = typ.IsNullable();
        Assert.IsFalse(result);
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAutodidactView Question on Stackoverflow
Solution 1 - C#Marc GravellView Answer on Stackoverflow
Solution 2 - C#Dean ChalkView Answer on Stackoverflow
Solution 3 - C#ErikView Answer on Stackoverflow
Solution 4 - C#Allon GuralnekView Answer on Stackoverflow
Solution 5 - C#Jon SkeetView Answer on Stackoverflow
Solution 6 - C#sclarke81View Answer on Stackoverflow
Solution 7 - C#CARLOS LOTHView Answer on Stackoverflow
Solution 8 - C#Mark JonesView Answer on Stackoverflow
Solution 9 - C#thinkbeforecodingView Answer on Stackoverflow
Solution 10 - C#Roel van MegenView Answer on Stackoverflow
Solution 11 - C#NetMageView Answer on Stackoverflow
Solution 12 - C#ipavluView Answer on Stackoverflow
Solution 13 - C#Lorenz Lo SauerView Answer on Stackoverflow
Solution 14 - C#VJPPazView Answer on Stackoverflow