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.
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.