Skip to content
Ian Griffiths By Ian Griffiths Technical Fellow I
C# 8.0 nullable references: more type system transcendence with DisallowNull

In my last blog in this series, I talked about the AllowNull attribute. This post shows its converse, DisallowNull. As with all the attributes relating to nullable references, the goal is to improve expressiveness, enabling the compiler to report more nullable-related problems without producing spurious warnings.

DisallowNull is pretty much the mirror image of AllowNull: whereas AllowNull lets you state that a null is allowed even when the type seems to state otherwise, DisallowNull lets you state that a null is not allowed even when the type system seems to state that it would be allowed. Much like AllowNull, DisallowNull is used with asymmetric properties, and generics.

Asymmetric properties

Occasionally, you might define a property that returns null if it has not been set yet, but where if someone does set it, they must provide a non-null value. You cannot express this through the C# type system alone, because a property's get and set accessors must have the same type. If you use a nullable type, you won't get warnings when code sets the property to a null value. If you use a non-nullable type, you won't get warnings for code that uses the property without checking for null.

DisallowNull resolves this dilemma. You can define a property with a nullable type, and then apply the DisallowNull attribute. The nullability of the property's type means the compiler will flag any attempts to use the value returned by the property without first checking it for null. But the presence of this attribute means it will also report any attempts to set it to a value that might be null.

The Introduction to Rx.NET (v6.1) 3rd Edition (2025) Book, by Ian Griffiths & Lee Campbell, is now available to download for FREE.

Generics

DisallowNull also gets used in generic code. It enables you to state that a particular usage of a type parameter does not accept null even when a nullable type is supplied as the type argument for that parameter. You can see this in use in the IEqualityComparer<T> interface from the .NET class library (which, as it happens, uses both AllowNull and DisallowNull):

public interface IEqualityComparer<in T>
{
    bool Equals([AllowNull] T x, [AllowNull] T y);
    int GetHashCode([DisallowNull] T obj);
}

The GetHashCode method here indicates that it does not accept nulls. So even if we instantiate this as IEqualityComparer<SomeClass?>, the effective signature of GetHashCode makes the argument type SomeClass (i.e., non-nullable) and not the SomeClass? (nullable) specified in the generic type argument. (Meanwhile, the arguments for Equals are both nullable regardless of whether the type argument is nullable or non-nullable.)

Programming C# 12 Book, by Ian Griffiths, published by O'Reilly Media, is now available to buy.

This is consistent with the non-generic version of the interface:

public interface IEqualityComparer
{
    bool Equals(object? x, object? y);
    int GetHashCode(object obj);
}

Here it's clear that the Equals method accepts nulls but that GetHashCode does not. This non-generic definition expresses this more directly through the presence or absence of ?, but the generic interface needs to use the AllowNull and DisallowNull attributes.

Conclusion

DisallowNull helps us out in two scenarios that are very similar to ones where its converse, AllowNull, is useful. One is where a type is stated once, but used in multiple ways, and we want different nullability in different places. The usual example of this is a property: we only get to declare the type of a property once, but we may require different nullability for the get and set accessors. Generics may also create scenarios where a type is expressed just once (as the type parameter) but then used in different ways. And then there's a second scenario, specific to generics, in which we want to be able to say that in cases where the argument for a type parameter is a reference type, we want the non-nullable version of that type, regardless of the nullability of the type argument.

FAQs

What does the DisallowNull attribute do in C# 8.0? DisallowNull lets you state that a null is not allowed even when the type system seems to indicate it would be. It is used with asymmetric properties and generics to improve the compiler's nullable reference analysis.
When would you use DisallowNull on a property? You would use DisallowNull on a property that returns null if it has not been set yet, but where if someone does set it, they must provide a non-null value. By defining the property with a nullable type and applying DisallowNull, the compiler will flag attempts to use the value without checking for null and also report attempts to set it to a potentially null value.
How is DisallowNull used in the IEqualityComparer<T> interface? In IEqualityComparer, the GetHashCode method uses DisallowNull on its parameter to indicate it does not accept nulls. So even if you instantiate IEqualityComparer, the effective signature of GetHashCode makes the argument type non-nullable (SomeClass) rather than the nullable SomeClass? specified in the generic type argument.
What is the relationship between DisallowNull and AllowNull? DisallowNull is the mirror image of AllowNull. While AllowNull lets you state that a null is allowed even when the type seems to state otherwise, DisallowNull lets you state that a null is not allowed even when the type system seems to allow it. Both are used with asymmetric properties and generics.

Ian Griffiths

Technical Fellow I

Ian Griffiths

Ian has worked across an extraordinary breadth of computing - from embedded real-time systems and broadcast television to medical imaging and cloud-scale architectures. As Technical Fellow at endjin, he brings this deep cross-domain experience to bear on the hardest technical problems.

A 17-time Microsoft MVP in Developer Technologies, Ian is the author of O'Reilly's Programming C# 12.0 and one of the foremost authorities on the C# language and high-performance .NET development. He's a maintainer of Reactive Extensions for .NET, Reaqtor, and endjin's 50+ open source projects.

Ian has created Pluralsight courses on WPF fundamentals, WPF advanced topics, WPF v4, and the TPL, and has given over 20 talks at conferences worldwide. Technology brings him joy.