Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Activator.CreateInstance creates value of type T instead of Nullable<T>

Tags:

c#

activator

Look at the sample code below

var genericNullableType = typeof(Nullable<>);
var nullableType = genericNullableType.MakeGenericType(typeof(bool));
var returnValue = Activator.CreateInstance(nullableType, (object)false);

For some reason returnValue variable will be of type bool and not bool?. Why is that and how could it be avoided?

UPD: Here is a screenshot from my VS enter image description here

like image 745
Demarsch Avatar asked May 29 '15 16:05

Demarsch


1 Answers

In this particular case you are using the overload of CreateInstance which returns object. The Nullable<T> is a struct hence to be represented as object it would need to be boxed. Yet Nullable<T> can't actually be boxed by rules of the CLR. Instead the underlying value or null is used. This is why you get a raw bool back here instead of bool?.

Documentation: https://msdn.microsoft.com/en-us/library/ms228597.aspx

EDIT

There seems to be some confusion around determining whether the type of a value is nullable or not. In particular it's been pointed out that the following prints System.Boolean and not System.Nullable``1[System.Boolean]:

var x = (bool?)true;
Console.WriteLine(x.GetType());

This code is also falling prey to boxing. The call to GetType has an implicit boxing operation because it's an invocation of a virtual method on object, not a method on Nullable<T>:

IL_0009: ldloc.0
IL_000a: box valuetype [mscorlib]System.Nullable`1<bool>
IL_000f: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
IL_0014: call void [mscorlib]System.Console::WriteLine(object)

The safest way to print out the actual type of a var value is to do the following trick with generics:

static void PrintType<T>(T value)
{
    Console.WriteLine(typeof(T));
}

PrintType(x);  // Prints System.Nullable`1[System.Boolean]
like image 70
JaredPar Avatar answered Nov 10 '22 22:11

JaredPar