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
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.
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.
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.
Function ContainsEven(data As List(Of Integer)) As Boolean
Return data.Any(Function(x) x Mod 2 = 0)
End Function
Function ContainsEven(data() As Integer) As Boolean
Return data.Any(Function(x) x Mod 2 = 0)
End Function
Function ContainsEven(data As List(Of Integer)) As Boolean
Return data.Exists(Function(x) x Mod 2 = 0)
End Function
Function ContainsEven(data() As Integer) As Boolean
Return Array.Exists(data, Function(x) x Mod 2 = 0)
End Function
| Method | Runtime | Mean | StdDev | Ratio | Allocated |
|---|---|---|---|---|---|
Any |
.NET 7.0 |
6.670 ms |
0.1413 ms |
1.00 |
40004 B |
Exists |
.NET 7.0 |
1.364 ms |
0.0270 ms |
0.20 |
1 B |
Any |
.NET Framework 4.6.2 |
5.380 ms |
0.0327 ms |
1.00 |
40128 B |
Exists |
.NET Framework 4.6.2 |
1.575 ms |
0.0348 ms |
0.29 |
- |
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