Pattern matching to find whether a value is not null was done using the is keyword with the respective expected type (included a cast if necessary). The pattern !(obj is object instance) returns true if obj is not null and false if obj is null. At the same time if obj is not null it is captured in the variable instance.
[Fact]
public void Old_pattern_matching_for_non_null_object()
{
var obj = new object();
if (!(obj is object instance)) // false
return;
if (instance is null) // false
throw new Exception("Never reached");
// this does not throw an exception (test passes)
}
With C#8 a new way of writing this was introduced using { } to denote non-null (without casting) which "simplified" the code to
[Fact]
public void Csharp_8_pattern_matching_for_non_null_object()
{
var obj = new object();
if (!(obj is { } instance)) // false
return;
if (instance is null) // false
throw new Exception("Never reached");
// this does not throw an exception (test passes)
}
With C#9 the new keyword not was introduced which was intended to simplify patterns such as !(x is null) to x is not null. If I now try to apply the new not keyword to a pattern includig { } I get a quite surprising result:
[Fact]
public void Csharp_9_pattern_matching_for_non_null_object()
{
var obj = new object();
if (obj is not { } instance) // false
return;
if (instance is null) // true
throw new Exception("Why the heck is this null");
// this does throw an exception (test fails)
}
Even though that obj is not null the instance variable is not initialized. And to get one better, by avoiding the obj variable instance will be initialized:
[Fact]
public void Csharp_9_pattern_matching_for_non_null_object_without_obj_variable()
{
if (new object() is not { } instance) // false
return;
if (instance is null) // false
throw new Exception("Never reached");
// this does not throw an exception (test passes)
}
Does anybody know if this is a desired behavior? If yes, what is the intent behind it?