Here is an example C# program with nullable reference types enabled:
using System;
using System.Collections.Generic;
using System.Linq;
MyStruct myStruct = new("A");
List<MyStruct> list = new() { myStruct };
MyStruct found = list.FirstOrDefault(item => item.Str == "B");
Console.WriteLine(found.Str.Length);
struct MyStruct
{
public readonly string Str;
public MyStruct(string str)
{
Str = str;
}
}
Note that MyStruct contains a non-nullable Str field. In theory this means that the Str field should never be nullable and the compiler will in almost all cases warn you if you leave it null.
However, one case in which a null value can slip in is if a non-initialized struct is returned via a generic method, such as with the FirstOrDefault call above. In this case, the Str field will be null but the C# compiler will give no warnings, either when accessing Str or when assigning the found variable, and thus the program crashes with a NullReferenceException when it tries to access found.Str.Length. (Another case if when reading a struct from an array.)
To make matters worse, some code analysis tools will falsely caution against checking to make sure found.Str isn't null. (For example, if I add if(found.Str != null) then Resharper will report that as "Expression is always true" and prompt to remove it even though it is definitely not true in this case.)
This seems like a major enough "leak" in C#'s nullability analysis that I have to wonder if I'm missing something about how to make the compiler understand this situation. Is there any way to "tell" the compiler that the found struct's fields might be null even though they are decalared non-nullable?
EDIT: To clarify, I'm aware of both this article and the answers to this question, which explain why this happens. But what I'm interested in is what to do about it. Specifically, is there any way to tell the compiler that a certain instance field may be null even though it is marked non-nullable, without changing the actual declaration of that field to be nullable. Similar to how you can postfix as expression with ! to tell the compiler, "trust me, this isn't null even though it is marked nullable", I'm looking to do the inverse and say "trust me, this may be null even though it's marked non-nullable". (Bonus points if there's a way to do this automagically with all fields of a struct instance, but I'm doubtful that's possible.)