Coder Perfect

What is the best way to see if an object is nullable?

Problem

How do I verify if a given object is nullable, or how do I put the following method into practise…

bool IsNullableValueType(object o)
{
    ...
}

Nullable value types are what I’m looking for. I hadn’t considered reference types.

//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 a boolean (System.Boolean) object with a value of true. What I truly wanted was a Nullable bool> object.

As a workaround, I decided to see if o is nullable and wrap obj with a nullable wrapper.

Asked by Autodidact

Solution #1

NullableT> and reference-type are the two types of nullables.

Jon has corrected me, saying that it’s difficult to acquire type if it’s boxed, but it’s possible with generics: – so how about the following? This is actually testing type T, but the obj parameter is only used for generic type inference (to make it easier to call) – it would operate virtually identically without it.

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
}

If you’ve previously boxed the value to an object variable, though, this won’t work.

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

Answered by Marc Gravell

Solution #2

Using method overloads, there is a very simple way.

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

Answered by Dean Chalk

Solution #3

This worked for me and appears to be straightforward:

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

Answered by Erik

Solution #4

“How to check if a type is nullable?” is actually “How to check if a type is Nullable>?” and may be generalized to “How to check if a type is a constructed type of some generic type?” to answer not only “Is Nullableint> a Nullable>?” but also “Is Listint> a List>?”

The Nullable is used in the majority of the solutions presented. GetUnderlyingType() is a method that, as the name implies, only works in the situation of Nullable>. I couldn’t find a general reflective solution that would work with any generic type, so I decided to share it here for posterity, despite the fact that this subject had already been answered.

To use reflection to see if a type is some kind of Nullable>, you must first convert your created generic type, such as Nullableint>, into the generic type definition, Nullable>. You can achieve this by calling the Type class’s GetGenericTypeDefinition() function. The resulting type can then be compared to Nullable>:

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

Any generic type can be used in the same way:

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

Several types may appear to be the same, but a varied number of type parameters indicates that they are not.

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

You can check for reference equality between Type objects because they are only created once per type. If you want to see if two objects have the same generic type specification, you can use the following syntax:

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

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

If you want to check if an object is nullable instead of a Type, you may combine the above technique with Marc Gravell’s answer to make a simple method:

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

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

Answered by Allon Guralnek

Solution #5

You could, for example, use:

return !(o is ValueType);

… yet an object isn’t nullable or otherwise – it’s a type that is. How did you want to put this to use?

Answered by Jon Skeet

Post is based on https://stackoverflow.com/questions/374651/how-to-check-if-an-object-is-nullable