How can I tell if an object's type is Nullable<T> using reflection?
If I have a Type
, is there some easy way to tell that it represents a nullable value type using Reflection? Ideally something a l开发者_JAVA百科ittle cleaner (and more correct) than:
static bool IsNullable(Type type)
{
return type.IsValueType && type.Name.StartsWith("Nullable");
}
type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)
You might also find Nullable.GetUnderlyingType(Type nullableType)
useful, to easily get the T
of the typeof(Nullable<T>)
you pass in.
Although @theCoop's answer is correct (there is nothing fundamentally wrong in placing his code into the body of the method you've provided), there are some giant gotchas here.
Nullable<T>
is treated by the run-time as a 'special' type that has some very peculiar semantics. In particular, when a Nullable<T>
is boxed:
- If
HasValue == true
, it behaves just like a boxedT
, making it impossible for downsteam code to tell if the created object was produced by boxing aT
or by boxing aNullable<T>
. Unboxing toT
andNullable<T>
are both possible. - If
HasValue == false
, boxing simply returnsnull
. Unboxing toT
will throw, unboxing toNullable<T>
will succeed, for whichHasValue == false
.
In either case, boxedNullableObject.GetType()
will not reveal that the object was produced by boxing a Nullable<T>.
I can't think of any other value-type that exhibits such strange behaviour.
For example, consider:
// Output: "System.Nullable`1[System.Int32]"
Console.WriteLine(typeof(int?));
object boxedNullableInt32WithValue = new int?(0);
// Output: "System.Int32", NOT "System.Nullable`1[System.Int32]"
Console.WriteLine(boxedNullableInt32WithValue.GetType());
object boxedNullableInt32WithoutValue = new int?();
// NullReferenceException is thrown
Console.WriteLine(boxedNullableInt32WithoutValue.GetType());
Consequently, writing a method such as:
public static bool IsObjectANullableT(this object obj) { ... }
is a really bad idea.
EDIT: On another note, I just realized there is a framework method that does what you need using the same technique as @theCoop's sample:Nullable.GetUnderlyingType
.
Usage:
static bool IsNullable(Type type)
{
return Nullable.GetUnderlyingType(type) != null;
}
EDIT: Just saw that this too was mentioned by @TheCoop in his answer. My mistake.
精彩评论