Search code examples
c#roslyn-code-analysis

How to resolve Roslyn CA1827 when using named constant


The following code is a simplified example of a class we're seeing roslyn error CA1827.

public class Test
{
    public const int NumberOfItemsToTriggerBehaviour = 1;

    public static void DoSomething(IEnumerable<string> items)
    {
        if (items.Count() < NumberOfItemsToTriggerBehaviour) //CA1827 is triggered here
        {
            // Do something
        }
    }
}

I'm guessing that roslyn is effectively treating the conditional statement as if (items.Count() < 1) in which case I understand that Any() would be preferable.

However, the goal with this code is to allow us to change the behaviour simply by updating the constant's value. We don't want to have to change the logic in the conditional statement if we change the minimum to... say 2 or greater.

I've considered the following solutions:

if (items.ToList().Count < NumberOfItemsToTriggerBehaviour) - This feels like unnecessary processing

public static readonly int NumberOfItemsToTriggerBehaviour = 1; - This loses the ability to have the value set at compile time

Is there another option I've not considered? Or should I raise this as an issue on the roslyn-analyzers github repo?

Any suggestions welcomed.


Solution

  • Ultimately, I have to agree with the compiler here in the general case - because if items is a non-trivial sequence (i.e. the IList etc short-cuts can't be used), then .Count() is going to need to do a considerable amount of work (a lot of .MoveNext() on an enumerator), where-as .Any() is much more efficient (only needing to do one call to .MoveNext()).

    So, if you're happy to ignore that aspect: that's when #pragma and [SuppressMessage(...)] come into play; the IDE will help you emit these in the right places. And if the constant changes such that this is no longer needed, it'll become IDE0079 instead (remove unnecessary suppression), so you can re-evaluate as the constant changes.