Skip to content
Ian Griffiths By Ian Griffiths Technical Fellow I
C# 8.0 nullable references: when methods don't return

This is the last in the sub-series on attributes for getting better results from C# 8's nullable references feature. (Next time I'll be getting back to some other aspects of nullable references.) As always, the goal here is to annotate our code with attributes that enable the C# compiler to do a better job with its nullable reference analysis—detecting more real problems, and reporting fewer false positives. The attributes I'm describing in this post help handle situations where a method might never return (e.g., because it throws an exception). The compiler needs to know when this can happen, because otherwise, it could incorrectly think that we're attempting to dereference a value that could be null.

With all the other posts in this sub-series, I've described attributes that were added specifically for nullable reference support. The attributes I'm describing here have been around since long before C# 8 added nullable references. They were originally designed to serve other purposes, but now have an additional role in a nullable-references-aware world.

DoesNotReturn

Earlier in this series I wrote about NotNull. This was primarily concerned with telling the compiler what it could infer about its inputs once the method returns, but as I also showed, it can be used in cases where a method might never return.

The DoesNotReturn attribute is also concerned with methods that don't return. But unlike NotNull which lets the compiler infer what will be true if the method returns, DoesNotReturn is simpler: it indicates that the annotated method will not return under any circumstances. This is typically used for methods that throw exceptions.

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

C# 8's nullable reference checking depends on the flow control analysis that C# has had since v1.0. This analysis supports the "definite assignment" rules that warn you when you might be trying to use a variable that has not yet been initialized. Some of the analysis the compiler was already performing for those purposes also has an impact on null handling warnings. This is why the DoesNotReturn attribute, which has been around for a long time, can now have an impact in null-aware code, as this example shows:

public static int Measure(string? pieceOf)
{
    if (pieceOf == null) { ThrowHelper(); }
    
    return pieceOf.Length;
}

[DoesNotReturn]
private static void ThrowHelper() => throw new ArgumentNullException();

This is somewhat contrived, but in codebases that localize exception messages, the use of helper methods to throw exceptions is common. Without the DoesNotReturn attribute, the pieceOf.Length expression will cause a compiler warning. But with that attribute present, the compiler correctly deduces that that line can only be reached if pieceOf is non-null (exactly as it would have done if the exception had been thrown directly from this method, without using a helper).

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

DoesNotReturnIf

The similar DoesNotReturnIf can be applied to a parameter, along with a boolean value indicating that the method will only fail to return if the argument in question has the specified boolean value. This is even closer in spirit to NotNull, in that it indicates that the method won't return under certain circumstances. But in this case, it's based purely on a boolean value, and not the nullness. Even so, the compiler's flow analysis can sometimes deduce null-related information from this attribute, as in this example:

private static void Test(string? arg)
{
    OnlyReturnsIfTrue(arg != null);
    Console.WriteLine(arg.Length);
}

private static void OnlyReturnsIfTrue([DoesNotReturnIf(false)] bool flag)
{
    if (!flag)
    {
        throw new InvalidOperationException();
    }
}

If the DoesNotReturnIf attribute were not present, this example would produce a warning on line 4—args.Length dereferences a variable of type string?. However, the attribute lets the compiler know that the method will not return in the case where its argument is false, and in this example, that means it won't return if arg is null. This enables the compiler to deduce that if the method does return, args must be non-null, and that it should not raise a warning for args.Length at that point in the code.

Conclusion

This is the last entry in the subseries on attributes that can improve the usefulness of C# 8's nullable references feature. Each of these enables us to make more detailed statements about our code's handling of nulls, improving the detail and quality of the compiler's analysis. Here's a quick roundup of each of them:

  • Overview – a quick tour round all of the attributes (the TL;DR version of the series)
  • AllowNull and DisallowNull – expressing distinctions the type system cannot capture for inputs
  • NotNull – enabling the compiler to infer that a reference is not null at a particular point in the code, even when the type system indicates that it is nullable
  • MaybeNull – indicating potentially null outputs in generic code regardless of the nullability of the type arguments
  • NotNullWhen, MaybeNullWhen, and NotNullIfNotNull – enabling the compiler to infer (non-)nullness conditionally
  • DoesNotReturn and DoesNotReturnIf (this post) – avoiding false warnings by letting the compiler know when methods won't return

FAQs

What does the DoesNotReturn attribute do? DoesNotReturn indicates that an annotated method will not return under any circumstances. This is typically used for methods that throw exceptions. The compiler uses this information for flow control analysis, enabling it to correctly deduce null-related information about code that follows calls to such methods.
How does DoesNotReturn differ from NotNull? NotNull lets the compiler infer what will be true if the method returns, while DoesNotReturn is simpler: it indicates that the method will not return at all. Both help the compiler with null-related analysis, but DoesNotReturn applies to methods that always throw exceptions rather than conditionally.
What is DoesNotReturnIf used for? DoesNotReturnIf can be applied to a boolean parameter to indicate that the method will only fail to return if that argument has a specified boolean value. The compiler's flow analysis can sometimes deduce null-related information from this, such as determining a variable is non-null because a validation method would have thrown if it were null.
Were DoesNotReturn and DoesNotReturnIf created specifically for nullable references? No, these attributes have been around since long before C# 8 added nullable references. They were originally designed to serve other purposes related to flow control analysis, but now have an additional role in enabling more accurate nullable reference analysis.
How does DoesNotReturn help with helper methods that throw exceptions? When you use helper methods to throw exceptions, without DoesNotReturn the compiler would warn about potential null dereferences on subsequent lines. With the attribute, the compiler correctly deduces that code after the helper call can only be reached if the checked value is non-null, exactly as it would if the exception were thrown directly.

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.