Yes, I've heard about this shift in modern C# that the typename by itself declares a non-null reference. This is ideal.
Declare stuff non-null wherever possible, it's the most common case.
Functions should take non-null parameters wherever possible. You can assume that the caller is also working mainly with non-nullable types. If he doesn't, it should be his burden to cast to non-nullabe before he calls you, especially if your function would immediately return on null. The caller shouldn't even call you then, and the solution is to take only non-null.
Some class member might be occasionally null during normal operation. Declare it nullable then, and then check for null when it appears in a method for the first time. C# has good code-flow analysis for this, this is excellent.
x?.foo() is more idiomatic than
if (x != null) x.foo() if you call only this single method. I don't know if the nullable C# type also behaves like a collection that has either 0 or 1 elements; if it does:
Idiomatic Scala: Your Options Do Not MatchInteresting that null violation is merely a warning in C# at compile time, I assume to keep back-compat with the heaps of earlier code. Treat this as an error in any code you touch, at least.
Avoid
!, it's the cast from nullable to non-null. It's okay at system boundaries (things from the network, interfacing with older libraries).
! is a hack to quickly work with legacy code that you didn't yet refactor to proper null/non-null types.
It's surprising, but at least consistent that
null! is allowed. I'd have to better understand the C# culture and history of the shift to non-nullable to argue how much the compiler should track stuff near
!. Looks like the compiler tracks only (whether stuff can be null), not (whether it can be non-null)? Or maybe it's not worth it to have a special case for exactly
null!.
Can you get the compiler to print the type of an expression?
null often has a special type in such languages that rarely appears in code, but it would be interesting what the compiler thinks is the type of
null!. Probably
null is of one of the types
typeof(null)typeof(null!)?and, consistently,
null! is of the type
typeof(null!)that apparently is then not empty (
null! belongs to this type) but it promises things that it can't eventually hold.
Really, it looks like
T x = null! is perfectly fine for the compiler because
T can accept
null after all, the warnings (without
!) are merely to help you at compile time, not to make the types work any different in the bytecode. In the bytecode,
T and
T? will probably be the same?
Very nice and fun quirks, thanks for looking into it!
-- Simon