I have a C# method (net6.0) similar to this:
bool TryDoSomething(out MyObject1? obj1, out MyObject2? obj2)
{
obj1 = DoSomethingElse();
obj2 = DoAnotherThing();
//Do some other things....
return obj1 != null && obj2 != null;
}
This is called by another method thusly:
bool CallingMethod()
{
if (!TryDoSomething(out var obj1, out var obj2))
return false;
obj1.PerformSomeAction();
obj2.PerformADifferentAction();
//Do many other things....
return true;
}
As is clear from the definition of TryDoSomething() and the fact that I am exiting early with return false, there is no way that obj1 or obj2 could be null by the time obj1.PerformSomeAction() or obj2.PerformADifferentAction() are called (the method would have returned early due to TryDoSomething() returning false before reaching those lines).
Yet, despite this, Visual Studio shows a squiggly line under obj1 and obj2 informing me that 'xxx' may be null here…..Dereference of a possibly null reference. (where ‘xxx’ is either ‘obj1’ or ‘obj2’).
How can this be happening? Is it a bug with Visual Studio itself?
>Solution :
You must declare the first method with attributes:
bool TryDoSomething([NotNullWhen(true)] out MyObject1? obj1, [NotNullWhen(true)] out MyObject2? obj2)
{
...
}
Inside your CallingMethod(), analysis makes no attempt at understanding the inner workings of the other method, TryDoSomething(...). So if there is some connection between the return value and the null state of the parameters, than must be communicated with attributes.
Read Attributes for null-state static analysis interpreted by the C# compiler to learn more about this.