I'm converting some code from C#5 to C#8, enabling nullable-check in compilation ruleset,
<Nullable>enable</Nullable>
then I met a problem like this:
class Person
{
public int MI { get; set; } = 3;
}
class UseWeakReference
{
public static void Main(string [] args)
{
Person person = new Person();
WeakReference<Person> wr = new WeakReference<Person>(person);
wr.TryGetTarget(out Person p1); // doesn't compile
Console.WriteLine(p1);
}
}
The compilation error is:
CS8600: Converting null literal or possible null value to non-nullable type.
What's the real cause of this compiling error, and how to fix it?
You can allow the out
parameter to be a possible null reference and compare it with null
value after method call
wr.TryGetTarget(out Person? p1);
if (p1 != null)
Console.WriteLine(p1);
Or simply check the return result of TryGetTarget
method: when it's true
, the p1
can't be null
var result = wr.TryGetTarget(out Person? p1);
if (result)
Console.WriteLine(p1);
The reason of compiler warning is that TryGetTarget
implemented like that
public bool TryGetTarget([MaybeNullWhen(false), NotNullWhen(true)] out T target)
{
// Call the worker method that has more performant but less user friendly signature.
T o = this.Target;
target = o!;
return o != null;
}
The nullability of out
parameter determined based on return value, according to [MaybeNullWhen(false), NotNullWhen(true)]
attributes, and can't be determined at compile time, only at runtime.
When you assign it to non-nullable reference, compiler warns you about possible problems. Checking the return result or use Person?
seems to be a proper solution here