In my current project, I need to check, for a given Type, if any of its properties is nullable. Nullable reference types is enabled in this solution so I want the result to show the property is nullable where the ?
is appended to the type name.
Let’s say we have some sample classes like these
public enum Genre
{
Drama,
Comedy,
Horror
}
public class Studio
{
public string Name { get; set; }
}
public class Director
{
public string Name { get; set; }
}
public class Movie
{
public string Title { get; set; }
public string? Description { get; set; }
public Genre Genre { get; set; }
public Genre? SubGenre { get; set; }
public DateTime ProductionDate { get; set; }
public DateTime? ReleaseDate { get; set; }
public Director Director { get; set; }
public Studio? Studio { get; set; }
public int DaysInProduction { get; set; }
public int? NumberOfStaff { get; set; }
}
I thought there should be a simple solution to this as it is not uncommon to know if a property is nullable. One of the most common answers is using Nullable.GetUnderlyingType
. However the result is not what I expect.
var type = typeof(Movie);
foreach (var property in type.GetProperties())
{
var isNullable = Nullable.GetUnderlyingType(property.PropertyType) != null;
Console.WriteLine($"Property {property.Name} is {(isNullable ? "nullable" : "not nullable")}");
}
When the property type is a reference, this solution always results in not nullable – string, Director and Studio.
Another common answer is to check if it’s a generic type and if its generic type is of Nullable<>
var type = typeof(Movie);
foreach (var property in type.GetProperties())
{
var isNullable = property.PropertyType.IsGenericType &&
property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>);
Console.WriteLine($"Property {property.Name} is {(isNullable ? "nullable" : "not nullable")}");
}
This also returns the same result as the previous solution.
After spending a bit more time researching a more reliable solution, I come across NullabilityInfoContext
which was introduced in .NET 6. This solution returns the result I expect.
var nullabilityContext = new NullabilityInfoContext();
var type = typeof(Movie);
foreach (var property in type.GetProperties())
{
var nullabilityInfo = nullabilityContext.Create(property);
var isNullable = nullabilityInfo.WriteState == NullabilityState.Nullable;
Console.WriteLine($"Property {property.Name} is {(isNullable ? "nullable" : "not nullable")}");
}