I am talking about the situation where there is no possible path leading to a specific variable being null at the point of the warning being thrown. Similar questions have been asked a lot before, especially here i found one highlighting this problem to an extend where even the C# program manager responded:
Why does this code give a "Possible null reference return" compiler warning?
However, i did not understand the explanation given. Or rather, they did talk about the lack of sophistication, and that the tracker only tracks a variables internal value, not the program flow around it. I want to provide an example of frustration i encounter consistently in C# that causes no issues in e.g. Java at all:
public double DoSomething(MyClass obj)
{
if (obj is null) throw new ArgumentException("Object is null!");
var result = OtherMethodCall(obj.A);
// or alternative example:
var result = obj.A * 10 / 3;
return result;
}
Here, both C# and Java compilers have no issues - no warnings are thrown about A being possibly accessed from a null object because they see that a null check is done immediately before. However, if i extract/refactor the validation code into a separate method, C# loses the ability to see it:
public double DoSomething(MyClass obj)
{
Validate(obj);
var result = OtherMethodCall(obj.A); // C# throws warning that A is possibly accessed from a null object
return result;
}
private void Validate(MyClass obj)
{
if (obj is null) throw new ArgumentException("Object is null!");
}
The Java compiler can still see the path before the variable (obviously, for java code we would have to add "throws" declarations to the method signatures) and C# seems to not see the path anymore. If i have 2 or more methods in this class which require the same validation code, which is not sophisticated enough to warrant a separate validator class added as a dependency, it "forces" me to repeat myself to not have any warnings in my code or add quite a lot of ugly preprocessor or other statements to suppress the warnings. Can anyone explain to me why this is a problem in C# still? In the link above, they said it is intended but they plan to fix some of these situations in c# 9.0, but i am using 10.0.