Work continues on nullable refence types for C# 8, revealing edge cases that need to be addressed before the final release and new opportunities for reducing the amount of boilerplate developers have to write.

Here are some of the open questions for nullable reference types:

Which takes precedence, MaybeNull or NotNull ?

or ? Should AllowNull and NotNull be allowed on value types?

and be allowed on value types? Should ! change top level nullability when there was no warning?

change top level nullability when there was no warning? Should ref arguments always be assumed to be assigned to?

Which conversions should preserve the nullable state of members?

Should we support var? , and if so, what are the open issues?

, and if so, what are the open issues? Along those lines, would we allow var? (x, y) = ... deconstructions?

deconstructions? Should we permit (or forbid) typeof(string?) , given that we can never honor the nullable annotation?

, given that we can never honor the nullable annotation? When we compute a nullable annotation in flow analysis, should we use the context?

Should the result of a dynamic invocation be treated as non-null, as it is generally outside the scope of static analysis?

Other questions have been answered. Here are some of the highlights that may affect how code is written.

The nullability of a conditional invocation ( x?.F() ) is always nullable.

) is always nullable. Throw statements and throw expressions yield a warning when their operand may be null.

No nullability warnings in unreachable code.

The nullability of anonymous types are part of its inferred signature.

Declarative Argument Null Checks

One of the holes in nullable reference types is they are merely a suggestion as far as the compiler is concerned. Even if you mark a parameter as non-nullable, there is nothing to stop someone from accidentally passing in a null, especially when using reflection or dynamic, which means you still need to add a null argument check at the beginning of your function.

With the Simplified parameter null validation, you’ll be able to tell the compiler it should create the null check for you. Two versions of the syntax have been proposed.

void Insert(string s!) void Insert(string! s)

In both cases the bang operator ( ! ) is used, either on the type name or the parameter name. The argument for the first version is it is an implementation detail of the function and not part of the method signature. The argument for the second version is it is more consistent with the nullable version ( void Insert(string? s) ) and perhaps it should be of the method signature. This is significant because if it’s part of the signature, then it can be applied to interface methods as well. And this then opens up questions about inheritance and overriding methods.

Another question is how it will be implemented? Options include:

C# emits the check inline in IL C# emits a call to a helper method in IL C# just emits a tag, allowing the JIT process to decide how to perform the check

Another question is what happens when the type is nullable ( int? ) but the null check is desired? If supported, this may result in an contradiction in the signature ( void Insert(int?! i) ).