In a generic method Foo<T> where T : new()
... is this expression always true?
typeof(T) == new T().GetType()
Sadly, no. For reference types (including nullable reference types) with default constructors then yes, but this doesn't hold true for nullable value types.
Where T
is int?
or DateTime?
or any other nullable value type, the result of new T()
is null. Calling GetType()
on null is of course going to result in a NullReferenceException
. But let's try something else:
static Type? WhichType<T>(T value) => value?.GetType();
This won't throw an exception, but may return null
. Now let's try it out:
var type1 = WhichType<int?>(0);
var type2 = WhichType((int?)0);
Since nullable value types are treated specially by the C# compiler, it's not entirely clear that the result of calling GetType()
on a nullable value type will return the inner type, and it makes some sense. Sadly it doesn't help you much when someone calls your generic method with the wrong type.
And in case you're wondering, it works on any value type not just value primitives:
public struct TestType { }
var type1 = WhichType<DateTime?>(DateTime.Now);
var type2 = WhichType<TestType?>(new TestType());
Where this may be an issue is when you're trying to compare the type of a value with an expected type where T
is a nullable value type. In this case you need to use a bit of code to figure things out.
var targetType = typeof(T);
if (targetType.IsConstructedGenericType &&
targetType.GetGenericTypeDefinition() == typeof(Nullable<>)
)
targetType = Nullable.GetUnderlyingType(targetType);
This will unwrap the Nullable<>
from the outer type if necessary, allowing you to compare it to the an object instance type.