Home > Software engineering >  How to tell C# nullable type checker that a variable cannot be null after a function call returns?
How to tell C# nullable type checker that a variable cannot be null after a function call returns?

Time:01-14

Short Version

How to make the C# nullable type checking compiler realize that the variable customer cannot be null after the call returns:

Constraints.NotNull(customer);

.NET Fiddle: enter image description here

Another Example

A better example, i came across in some old code:

Customer? currentCustomer;

//...

EnsureCurrentCustomer(); 

DoSomethingWithIt(currentCustomer); // guaranteed not null because EnsureCurrentCustomer did it,
             // but the compiler doesn't know that.

We need a way for EnsureCurrentCustomer to tell the C# 8 nullable type checker that the variable currentCustomer cannot be null after EnsureCurrentCustomer function returns.

How do?


ChatGPT says the only way to do it is to use the JetBrains [NotNull] constraint; which i don't have access to.

CodePudding user response:

If you just change the call site ever so slightly:

customer = Constraint.NotNull(customer, "Customer");

Then you can just do:

public static class Constraint {
    public static T NotNull<T>(T? t, string? msg="") where T: notnull {
        if (t is null) {
            throw new Exception("Object cannot be null " msg);
        }
        return t;
    }
}

For the second example, assuming currentCustomer is a field, you can use MemberNotNull:

[MemberNotNull("s")]
void EnsureCurrentCustomer() {
    if (currentCustomer is null) {
        throw new Exception(...);
    }
}

If currentCustomer is instead a local variable and EnsureCurrentCustomer is actually a local function, then I would do something similar to Constraint.NotNull, i.e. changing the caller to:

currentCustomer = EnsureCurrentCustomer()

and just use a non nullable Customer for the return type.

CodePudding user response:

This is achieved using the [NotNull] annotation on the argument being verified in your guard-clause method. A good reference for this is in the ArgumentNullException.ThrowIfNull static method. The summary of the NotNullAttribute says:

Specifies that an output will not be null even if the corresponding type allows it. Specifies that an input argument was not null when the call returns.

You can also refer to xUnit's Assert.NotNull assertion, which does the same thing.

  • Related