All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sonar.plugins.csharp.S6605.html Maven / Gradle / Ivy

There is a newer version: 10.2.0.105762
Show newest version

Why is this an issue?

Both the List.Exists method and IEnumerable.Any method can be used to find the first element that satisfies a predicate in a collection. However, List.Exists can be faster than IEnumerable.Any for List objects, as well as requires significantly less memory. For small collections, the performance difference may be negligible, but for large collections, it can be noticeable. The same applies to ImmutableList and arrays too.

Applies to

What is the potential impact?

We measured at least 3x improvement in execution time. For more details see the Benchmarks section from the More info tab.

Also, no memory allocations were needed for the Exists method, since the search is done in-place.

Exceptions

Since LINQ to Entities relies a lot on System.Linq for query conversion, this rule won’t raise when used within LINQ to Entities syntaxes.

How to fix it

The Exists method is defined on the collection class, and it has the same signature as Any extension method if a predicate is used. The method can be replaced in place.

Code examples

Noncompliant code example

bool ContainsEven(List<int> data) =>
    data.Any(x => x % 2 == 0);
bool ContainsEven(int[] data) =>
    data.Any(x => x % 2 == 0);

Compliant solution

bool ContainsEven(List<int> data) =>
    data.Exists(x => x % 2 == 0);
bool ContainsEven(int[] data) =>
    Array.Exists(data, x => x % 2 == 0);

Resources

Documentation

Benchmarks

Method Runtime Mean Standard Deviation Allocated

Any

.NET 7.0

6.670 ms

0.1413 ms

40004 B

Exists

.NET 7.0

1.364 ms

0.0270 ms

1 B

Any

.NET Framework 4.6.2

5.380 ms

0.0327 ms

40128 B

Exists

.NET Framework 4.6.2

1.575 ms

0.0348 ms

-

Glossary

The results were generated by running the following snippet with BenchmarkDotNet:

private List<int> data;
private readonly Random random = new Random();

[Params(1_000)]
public int N { get; set; }

[GlobalSetup]
public void Setup() =>
    data = Enumerable.Range(0, N).Select(x => 43).ToList();

[Benchmark(Baseline = true)]
public void Any()
{
    for (var i = 0; i < N; i++)
    {
        _ = data.Any(x => x % 2 == 0);          // Enumerable.Any
    }
}

[Benchmark]
public void Exists()
{
    for (var i = 0; i < N; i++)
    {
        _ = data.Exists(x => x % 2 == 0);       // List<T>.Exists
    }
}

Hardware configuration:

BenchmarkDotNet=v0.13.5, OS=Windows 10 (10.0.19045.2846/22H2/2022Update)
11th Gen Intel Core i7-11850H 2.50GHz, 1 CPU, 16 logical and 8 physical cores
.NET SDK=7.0.203
  [Host]               : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
  .NET 7.0             : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
  .NET Framework 4.6.2 : .NET Framework 4.8.1 (4.8.9139.0), X64 RyuJIT VectorSize=256




© 2015 - 2024 Weber Informatics LLC | Privacy Policy