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