Home > Enterprise >  Pattern matching test for null and assign
Pattern matching test for null and assign

Time:08-14

Reading the docs I am not 100% clear on the implications of pattern matching and assignment when checking nullability

Consider:

#nullable enable

record EmployeeData(string Name, int Age);

bool F(string employeeName) {
  EmployeeData? employee = repository.Get(employeeName); // return null if not found
  if (employee is null) return false;
  // do something with employee it is not null
  return true;
}

Can this correctly be written as:

bool F(string employeeName) {
  if (repository.Get(employeeName) is not EmployeeData employee) return false;
  // do something with employee it is not null
  return true;
}

Note: I would like to do:

  if (repository.Get(employeeName) as EmployeeData employee is null) return false;

which is much clearer, but that does not compile :( or is there a better way ?

CodePudding user response:

Let's try to prove employee is not null.

We can start by finding out exactly when will the pattern not EmployeeData employee match.

not EmployeeData employee is a not pattern with a declaration pattern EmployeeData employee as its negated pattern. According to the documentation, a not pattern

matches an expression when the negated pattern doesn't match the expression.

and

a declaration pattern with type T matches an expression when an expression result is non-null and any of the following conditions are true:

  • The run-time type of an expression result is T.

  • The run-time type of an expression result derives from type T [...]

  • [...]

(I've omitted the rest of the conditions in that list because they are not relevant to your question)

Combining these two facts, we can see that your not EmployeeData employee would match if the negation of the above quote is true, which is when

the expression result is null or all of the following conditions are true:

  • The run-time type of an expression result is not T.

  • The run-time type of an expression result does not derive from type T [...]

  • [...]

This is when your if branch would execute.

From your original code, it seems like repository.Get is declared to return EmployeeData?, so the expression result would always be of runtime type EmployeeData or one of its derived type (nullable reference types don't exist in runtime), so the "all of the following conditions" part above would be always false. All that's left is the "the expression result is null".

Therefore, we have shown that your if branch would execute when repository.Get(employeeName) is null, which is the same as your original code.

If the if branch doesn't execute, then the code after it would. It also implies (by modus tollens) that repository.Get(employeeName) is not null.

Since the value of repository.Get(employeeName) is assigned to the declared employee, as it said here:

With a declaration pattern, you can also declare a new local variable. When a declaration pattern matches an expression, that variable is assigned a converted expression result [...]

we have proven that employee is not null.

CodePudding user response:

why don't you try

if (repository.Get(employeeName)  is null) return false;
  •  Tags:  
  • c#
  • Related