1
votes

I have a complex object I want to check is valid. I have a method to check it, but C# nullability checks don't know about them:

#nullable enable
...

bool IsValid(Thing? thing) 
{
    return thing?.foo != null && thing?.bar != null;
}

...

if(IsValid(thing)) 
{
   thing.foo.subProperty; // CS8602 warning: foo is possibly null here

Is there any way to apply something like TypeScript's type-gates here? If IsValid is true then we know that thing.foo is not null, but the C# analyser can't see inside the function. If I inline the check it can, but then I'm copy-pasting code and this is a simple example.

Is there any annotation or pattern where I can have the nullability analysis with the more complex checks?

1
From .NET 5 onwards you can use MemberNotNullWhen, but that will only work if IsValid is made a method of Thing. - Jeroen Mostert
Have opened a C# language discussion about allowing MemberNotNullWhen in more places: github.com/dotnet/csharplang/discussions/4563 - Rikki Gibson
Ah, that's frustrating, as I want to validate that both thing is not null and thing.property is not null when it passes the validity check, it looks like I can do one or the other but not both. - Keith

1 Answers

2
votes

You can use the null-forgiving operator like this:

if (IsValid(thing))
{
    thing.foo!.subProperty;
}

As @JeroenMostert points out, while it won't help you with foo, an alternative is the NotNullWhen attribute.

The compiler knows thing is not null here, but foo might still be null.

bool IsValid([NotNullWhen(true)] Thing? thing)
{
    return thing?.foo != null && thing?.bar != null;
}

if (IsValid(thing))
{
    thing.foo;
}