[OT] my experience with nullable types (C#)
Richard (Rikki) Andrew Cattermole
richard at cattermole.co.nz
Wed Apr 30 08:26:16 UTC 2025
On 30/04/2025 7:17 PM, Kagamin wrote:
> Finally I had my chance to cope with nullable types in one of our C#
> codebases, and the experience wasn't nice.
>
> I had a prejudice that nullable types give some kind of promise that you
> will have only a few of them, but now that I think about it I can't
> remember anyone making this promise, and reality is quick to shatter
> this prejudice in a very ugly way.
> If you have a nullable type, all code now sees it as nullable, and you
> must insert null checks everywhere, even if you know it's not null by
> that point, and the volume of this null check spam is uncomfortably
> large. It's also not very clear what's the difference between me
> spamming null checks everywhere by hand and processor doing the same
> automatically.
> Nullable types are retrofitted in dotnet and all legacy interfaces
> return nullable types, this greatly increases number of null checks.
> DTOs are destroyed. How can you even have a DTO with nonnullable field?
> Initialize it to a stub value in default constructor? That's 1)
> NullObject pattern, 2) allocates extra garbage. The number of null
> checks is greatly increased.
> Null check operator has pretty high precedence. If you want to null
> check an expression, you'll need to surround it with braces, this is
> especially annoying with await expression as checking the result of
> await is the best place for null check. Exclamation also looks like
> negation, imagine parsing `if(a! == b)`, this happens unexpectedly often.
You are not alone in your pain tolerance for DFA based language features.
Without whole program analysis (purely research currently), you're stuck
with accepting false positives if you want a 100% solution. This is a
big failing point of DIP1000, it tries to be a 100% solution, and the
resulting false positives are well beyond a lot of peoples pain threshold.
Given the different target audience of application VM's, and the fact
that each language is doing it similarly, I expect that eliminating an
entire class of issues their solution is right for them.
However they are not D, and encoding nullability into the type system
like this with false positives isn't the right default. BUT this should
not be the only mode that D compilers support (I would be using a 100%
solution).
I.e. these cases should be caught by default:
```d
int* ptr;
int v = *ptr; // SEGFAULT
```
```d
int* identity(int* ptr) => ptr;
int v = *identity(null); // SEGFAULT
```
You can extend this to escape analysis, and uninitialized memory.
More information about the Digitalmars-d
mailing list