Exploring the non-nullable type warnings in C# 8


C# 8 will bring us many new exciting features, and personally my favorite feature is the non-nullable type one.

If you are new to this feature, then I recommend you first read up on it here:

When I researched this new feature online, I found that most of the examples looked something like this: (This code will result in the following two null-warnings)


private static string DoMagicStuff(string? input)
{  
 if (input.Length > 0)  
 
//Dereference of a possibly null reference        
  return input.ToUpper().Trim();
  else
  return null; //Possible null reference return
} 

This is of course cool, but what other warnings can be generated by the Roslyn compiler? To what extent can the compiler detect null-warnings? In this blog post, I want to explore as many of the null-related warnings as possible.

So, to get a better feeling for what is actually possible, let’s find out!

Where to find all the possible compiler warnings?

The first step is to look at all the related null-warnings that exists, and from that get a better clue for what is possible.

During my research I found that the Roslyn compiler source-code itself is the best source for this information. The source-code for the compiler is hosted on GitHub here. In the source-code I located the ErrorCode enum located here. It contains a big enum of all the possible error codes, and conveniently the null related warnings I found were located in the range between 8597 -> 8715.

An example from this enum is:


internal enum ErrorCode
{    
     // ...    
     WRN_ThrowPossibleNull = 8597,    
     ERR_IllegalSuppression = 8598,    
     WRN_ConvertingNullableToNonNullable = 8600,    
     WRN_NullReferenceAssignment = 8601,    
     WRN_NullReferenceReceiver = 8602,    
     WRN_NullReferenceReturn = 8603,    
     WRN_NullReferenceArgument = 8604,   
     WRN_UnboxPossibleNull = 8605,    
     WRN_NullReferenceIterationVariable = 8606,    
     WRN_DisallowNullAttributeForbidsMaybeNullAssignment = 8607,    
     WRN_NullabilityMismatchInTypeOnOverride = 8608,    
     // ...
}


The warning strings

This is a great start, but having the warning name and number is not so helpful. I want to see the actual warning strings, so where can I find them?

It turns out that I can, for a given warning above, based on the enum name, lookup the corresponding warning message string in the file CSharpResources.resx , located here. As an example, for the warning WRN_NullReferenceReturn , the corresponding warning string is:


<data name="WRN_NullReferenceReturn" xml:space="preserve">
    <value>Possible null reference return.</value>
</data>

Cool! I have located all the null related warnings messages in the compiler source code, but now the question is how can I write C# 8 code, to trigger most of these warnings?


The warnings

The warnings that I have created test code for are the following:

Exceptions CS8597 Thrown value may be null.

Partial classes CS8611 Nullability of reference types in type of parameter 'XXX' doesn't match partial method declaration.

Delegates CS8621 Nullability of reference types in return type of 'XXX' doesn't match the target delegate 'YYY'. CS8622 Nullability of reference types in type of parameter 'XXX' of 'YYY' doesn't match the target delegate 'ZZZ'.

Inheritance CS8609 Nullability of reference types in return type doesn't match overridden member. CS8610 Nullability of reference types in type of parameter 'XXX' doesn't match overridden member.

Interface CS8613 Nullability of reference types in return type of 'XXXX' doesn't match implicitly implemented member 'YYY'. CS8614 Nullability of reference types in type of parameter 'XX' of 'YYY' doesn't match implicitly implemented member 'ZZZ'. CS8616 Nullability of reference types in return type doesn't match implemented member 'XXX'. CS8617 Nullability of reference types in type of parameter 'XXX' doesn't match implemented member 'YYY'.

Field and properties CS8618 Non-nullable property 'XXX' is uninitialized. CS8618 Non-nullable field 'XXX' is uninitialized.

Methods calls CS8603 Possible null reference return. CS8604 Possible null reference argument for parameter 'XXXX' in 'YYYY'. CS8620 Argument of type 'XXX' cannot be used for parameter 'YYY' of type 'ZZZ' in 'AAA' due to differences in the nullability of reference types. CS8624 Argument of type 'XXX' cannot be used as an output of type 'YYY' for parameter 'ZZZ' in 'AAA' due to differences in the nullability of reference types.

Assignments CS8600 Converting null literal or possible null value to non-nullable type. CS8601 Possible null reference assignment. CS8602 Dereference of a possibly null reference. CS8605 Unboxing a possibly null value. CS8606 Possible null reference assignment to iteration variable CS8619 Nullability of reference types in value of type 'XXX' doesn't match target type 'YYY'. CS8625 Cannot convert null literal to non-nullable reference type. CS8629 Nullable value type may be null.

Generics CS8631 The type '{3}' cannot be used as type parameter '{2}' in the generic type or method '{0}'. Nullability of type argument '{3}' doesn't match constraint type '{1}'.</value> CS8634 The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.


The majority of the non-nullable type issues are represented as warnings, there are also a few that are treated as compiler errors, and I decided to ignore those because I want my code to actually compile.

The Source code

The source code for the project that will trigger all the warnings above can be found on GitHub here.

Conclusions

It’s really impressive how many warnings related to null that the compiler can generate, and I assume this list will grow over time as the compiler and this feature evolves.

Feedback wanted

Have you found some code that does cover a null related warning that is not yet covered? Then contact me at tore@edument.se or send me a pull request!


About the author

Tore has worked with everything from low-level programming in assembler to building event-driven applications with the CQRS architecture. Everyday, he works to educate developers where he likes to share his experiences from his various projects. As a person, Tore is constantly curious about new technologies and his motto "One can not say anything until one can explain it to others" is his guiding star. Do Want to learn more about C# and .NET core? Then explore the training offering by Edument, we have training classes all the way from beginning to advanced C#/.NET. See our courses in .NET.

0 comments