Reputation: 13655
Surprisingly the following code fails the Assert:
int? wtf = 0;
Assert.IsType<Nullable<int>>(wtf);
So just out curiosity, how can you determine if a given instance is a Nullable<> object or not?
Upvotes: 43
Views: 28422
Reputation: 127
Only this way worked in my case using .net core 7
MyClass mclass = new MyClass();
PropertyInfo[] properties = mclass.GetType().GetProperties();
foreach (PropertyInfo propertyInfo in properties)
{
bool nullable = propertyInfo.GetMethod is null ? false : new NullabilityInfoContext().Create(propertyInfo.GetMethod.ReturnParameter).ReadState == NullabilityState.Nullable;
if (nullable)
{
//some script to do
}
}
Upvotes: 3
Reputation: 813
This works for me to check wether a type is Nullable or not..
type.Assembly.FullName.StartsWith("System") && type.Name.Contains("Nullable");
Upvotes: 0
Reputation: 139
Based on Vladimir answer:
public static class GenericExtensions
{
public static bool IsNullable<T>(this T item) =>
TypedReference.GetTargetType(__makeref(item)).FullName.Contains("System.Nullable");
}
Usage:
int? nullableInt = 42;
bool nIntIsNullable = nullableInt.IsNullable();
Duration: <2ms on average machine.
Remarks:
Contains("System.Nullable")
can be more specific.Upvotes: 0
Reputation: 2175
It works fo me, hope for you too.
public static bool IsNullable(this Type type)
{
return Nullable.GetUnderlyingType(type) != null;
}
Upvotes: 0
Reputation: 852
I like the @jon-skeet answer but it only works if you know the type you are testing against. In our world we are using reflection to open up objects and test values against regex expressions.
simplifying the extension to work for any type worked better for us.
public static bool IsNullable(this Type type)
{
return Nullable.GetUnderlyingType(type) != null;
}
generics are life's blood but sometimes... :)
Upvotes: 11
Reputation: 24730
Here is what I came up with, as everything else seemed to fail - at least on Portable Class Library / DotNet Core with >= C# 6
Basically you extend generic Type Object
and Nullable<T>
and use the fact that the static extension method that matches the underlying type is going to be invoked and takes precedence over the generic T
extension-method.
public static partial class ObjectExtension
{
public static bool IsNullable<T>(this T self)
{
return false;
}
}
and one for Nullable<T>
public static partial class NullableExtension
{
public static bool IsNullable<T>(this Nullable<T> self) where T : struct
{
return true;
}
}
Using Reflection and type.IsGeneric
and type.GetGenericParameters()
did not work on my current set of .NET Runtimes.
Upvotes: 0
Reputation: 7475
int? i = 0;
var type = TypedReference.GetTargetType(__makeref(i));
var isNullable = type.IsGenericType &&
type.GetGenericTypeDefinition() == typeof(Nullable<>);
Upvotes: 6
Reputation: 86729
What namespace is Assert
in?
The following returns true
as you would expect:
int? wtf = 0;
if (typeof(Nullable<int>).IsInstanceOfType(wtf))
{
// Do things
}
Although its worth noting that typeof(Nullable<int>).IsInstanceOfType(42)
also returns true - this is because this method accepts an object
and so gets boxed as a Nullable<int>
.
Upvotes: 0
Reputation: 1500515
Well firstly, Nullable<T>
is a struct, so there isn't an object as such. You can't call GetType()
, as that will box the value (at which point you either get null and thus an exception, or a boxed non-nullable value and therefore not the type you want).
(Boxing is what's messing up your assertion here - I would assume that IsType
accepts object
.)
You can use type inference though to get the type of the variable as a type parameter:
public bool IsNullable<T>(T value)
{
return Nullable.GetUnderlyingType(typeof(T)) != null;
}
That's not a huge amount of use when you know the exact type at compile-time as in your example, but it's useful for generics. (There are alternative ways of implementing it, of course.)
What's your real life situation? I assume it's not an assertion like this, given that you know the answer to this one at compile time.
Upvotes: 81