[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