Since .NET 6, Linq added an overload to object.FirstOrDefault(lamda, object default) which allows the developer to offer a default object to read data from in the case that a match was not found for the lamda expression. An example is below:
In the above case, if no Value exists in the list of AllValues equal to “MyDesiredValue”, the resulting value for the Text property would be “Show Me”. There should never be a null in this case because we provided a non-null default.
SonarQube currently flags above code as a medium bug with the explanation that it could result in a null exception which is not possible. I believe this needs to be added to acceptable logic.
Welcome to the community and thanks for this report!
Can you give your context for this? I.e. are you on SonarQube Cloud? SonarQube for IDE (flavor and version)? SonarQube self-managed (flavor and version)?
Thanks for the report, and thanks for providing the SonarQube version.
We were not able to reproduce the false positive with the code and information provided so far. A few follow-up questions that will help us narrow this down:
1. Target framework
Which target framework is the project compiled for? For example net8.0, net9.0, or net48? You can find this in your .csproj file under <TargetFramework> (or <TargetFrameworks>).
This matters because the .NET 6+ overload FirstOrDefault(predicate, defaultValue) carries a [return: NotNullIfNotNull("defaultValue")] annotation in the BCL — but only when compiled against a nullable-annotated runtime (i.e. .NET 6+). If the project targets net48, that annotation is absent and the analyzer cannot rely on it.
2. Analyzer version
Could you add /d:sonar.verbose=true to your SonarScanner begin step, re-run the analysis, and share the following two lines from the begin step logs?
SonarScanner for MSBuild x.y
...
Processing plugin: csharp ... version x.y
This tells us which version of the C# analyzer is being used and helps confirm whether the version you are running already contains a fix for this pattern.
3. Complete code sample
Could you share a more complete code snippet that reproduces the issue — ideally a self-contained method or class — with a comment on the exact line where the issue is raised? Something like:
var result = items.FirstOrDefault(x => x.Value == "foo", defaultValue); // S2259 raised here?
result.Text; // or here?
This will help us pinpoint whether the issue is raised on the FirstOrDefault call itself or on the subsequent member access.