S3267 is being reported by sonar lint for code that is compliant

This is a bit of code that generates data for testing. SonarLint is reporting that I should simplify this by using a .Select()

or if you prefer the text


var recordValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (var sourceField in newItemSmokeTestFieldSet.SourceFields)
{
     recordValues.Add(sourceField.Name, $"{sourceField.Name}_Data{recordIndex}");
}

This is aligned with the examples of compliant given for S3267 and there would not be any readability gains by changing this around to be something like

var recordValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (var sourceFieldName in newItemSmokeTestFieldSet.SourceFields.Select(sf => sf.Name)
{
      recordValues.Add(sourceFieldName, $"{sourceFieldName}_Data{recordIndex}");
 }

I think that would cause the allocation of an additional array to hold the source field names to iterate. Please address this

Hi,

What language is this?

And - to make sure you’re seeing the latest implementation of the rule - what SonarLint version are you using? And if you’re in connected mode, what version of SonarQube, or is it SonarCloud?

 
Thx,
Ann

Language is c#, solution is bound to a sonarcloud project, and sonarlint is 6.9.0.54300

1 Like

Hi @StingyJack,

you mentioned two aspects, which you would like to see addressed:

No readability gains

What the rule complains about specifically is the access of sourceField.Name (it’s accessed twice) in your example. The idea is that you only want to access a small part of “SourceField” in the loop and you should “Select” what you are interested in outside the loop.
Because Select(sf => sf.Name) accesses the name property only once, the equivalent code would look more like this:

foreach (var sourceField in newItemSmokeTestFieldSet.SourceFields)
{
    var sourceFieldName = sourceField.Name;
     recordValues.Add(sourceFieldName, $"{sourceFieldName}_Data{recordIndex}");
}

You save one line of code with the Select. I would consider your example an edge case with respect to readability because you gain just a little but it is in the spirit of the rule.

Allocation of an additional array

The short answer is: There is no array allocation caused by Select.

The long answer is, that there is an allocation of a delegate Func<SourceField, string> and of an IEnumerator<string> but there is no array allocation. You can see what is generated behind the scenes on sharplab. The allocations caused by LINQ are a known downside over procedural code but (almost always) neglectable.

I can not see what we can do on our side as the rule behaves as expected. You can use the supression mechanisms to silence the rule or disable the rule in your SonarCube quality profile if you object to the rule in general.

Best regards Martin