Find type of nullable properties via reflection
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
When you inspect properties through reflection in modern C#, there are two different nullable stories to handle. Nullable value types such as int? are represented directly in the runtime type system, while nullable reference types such as string? are mostly expressed through compiler-generated metadata.
Start With the Two Nullable Cases
For value types, reflection is straightforward. An int? property is really Nullable<int>, so Nullable.GetUnderlyingType can tell you whether a property is a nullable value type.
Reference types are different. string and string? both appear as System.String at runtime, so PropertyInfo.PropertyType alone cannot tell you whether the source code allowed null. For that case, use NullabilityInfoContext.
Detect Nullable Value Types
This helper handles value types first:
If the property type is int?, the helper returns true. If the property type is plain int, it returns false.
Detect Nullable Reference Types
For C# 8 and later, NullabilityInfoContext is the simplest reliable API. It reads the nullability metadata that the compiler emitted.
For Nickname, PropertyType is still String, but info.ReadState reports Nullable. For Score, Nullable.GetUnderlyingType reports Int32, which tells you the property is int?.
Return the Effective Type and Nullability Together
In many reflection-heavy systems, the practical goal is not just "is this nullable?" but "what underlying type should I treat this as?" A small helper can package both answers in one place.
This is a good shape for serializers, schema generators, or admin tooling that needs consistent metadata from reflected properties.
Conditions for Accurate Results
NullabilityInfoContext depends on compiler metadata. That means the project should have nullable annotations enabled, usually through #nullable enable in the file or the project-wide nullable setting in the .csproj. If the metadata is missing, reflection cannot reconstruct source-level intent reliably.
Also remember that generic types and nested members may need deeper inspection. For example, a List<string?> property is different from List<string>, and the nullability of the element type is separate from the nullability of the property itself.
Common Pitfalls
- '
PropertyInfo.PropertyTypecannot distinguishstringfromstring?.' - '
Nullable.GetUnderlyingTypeonly helps withNullable<T>, not nullable reference types.' - If nullable annotations were disabled at compile time, reflection cannot tell you what the source intended.
- Collections may have nullability rules for both the property and the contained element type.
Summary
- Use
Nullable.GetUnderlyingTypefor nullable value types such asint?. - Use
NullabilityInfoContextfor nullable reference types such asstring?. - Treat value-type nullability and reference-type nullability as two separate reflection problems.
- If you need runtime metadata for tooling, return both the effective type and the nullability flag together.

