Why is this an issue?

Using explicit loops for filtering, selecting, or aggregating elements can make code more verbose and harder to read. LINQ expressions provide a more concise and expressive way to perform these operations, improving code clarity and maintainability.

Performance Considerations

If the affected code is part of a performance-critical hot path and that the fix would negatively impact performance, you can self-declare the PerformanceSensitiveAttribute in your codebase, or use the one provided by Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers:

[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true, Inherited = false)]
public sealed class PerformanceSensitiveAttribute() : Attribute;

[PerformanceSensitiveAttribute]
List<string> Method(IEnumerable<string> collection, Predicate<string> condition)
{
  var result = new List<string>();
  foreach (var element in collection)  // Without the attribute, this would raise an issue
  {
    if (condition(element))
    {
      result.Add(element);
    }
  }
  return result;
}

The rule will respect the AllowGenericEnumeration property:

[PerformanceSensitive("Enumeration", AllowGenericEnumeration = true)]
List<string> Method(IEnumerable<string> collection, Predicate<string> condition) { }

In this case, the rule will not be disabled even if the method is marked with the PerformanceSensitiveAttribute attribute.

How to fix it

Replace explicit loops and conditional blocks with equivalent LINQ expressions.

Use the System.Linq.Async package to enable LINQ operations on IAsyncEnumerable prior to .NET 10.

Code examples

Noncompliant code example

List<string> Method(IEnumerable<string> collection, Predicate<string> condition)
{
  var result = new List<string>();
  foreach (var element in collection)  // Noncompliant
  {
    if (condition(element))
    {
      result.Add(element);
    }
  }
  return result;
}
List<string> Method(IEnumerable<MyDto> collection)
{
  var result = new List<string>();
  foreach (var element in collection) // Noncompliant
  {
    var someValue = element.Property;
    if (someValue != null)
    {
      result.Add(someValue);
    }
  }
  return result;
}
public void Method(List<string> list)
{
  foreach (var element in list)
  {
    var someValue = element.Length;
  }
}
async void Method(IAsyncEnumerable<int> collection)
{
  await foreach (var element in collection)
  {
    if (element is 42)
    {
      Console.WriteLine("The meaning of Life.");
    }
  }
}

Compliant solution

List<string> Method(IEnumerable<string> collection, Predicate<string> condition) =>
  collection.Where(x => condition(x)).ToList();
List<string> Method(IEnumerable<MyDto> collection) =>
  collection.Select(x => x.Property).Where(y => y != null).ToList();
void Method(List<int> list)
{
  foreach (var length in list.Select(x => x.Length))
  {
    var someValue = length;
  }
}
async void Method(IAsyncEnumerable<int> collection)
{
  await foreach (var element in collection.Where(x => x is 42)))
  {
    Console.WriteLine("The meaning of Life.");
  }
}

Resources

Documentation