0

Given:

Dim values = {"First", "Second", "Third", "Fourth", "Fifth"}
Dim searchValue = "fourth"
Dim isPresent = False

Is it more efficient to do this:

isPresent = values.Any(Function(x) String.Compare(x, searchValue, True) = 0)

or this:

For Each value In values
    If (String.Compare(value, searchValue, True) = 0) Then
        isPresent = True
        Exit For
    End If
Next

Basically, my question is: does the Any method short-circuit -- as the For Each loop does -- when it encounters its first element that satisfies the predicate, and if that is the case, does it do so any faster than the O(n) of the For Each operation shown above?

Please note: my question is not about finding a string in a collection of strings. I know there are plenty of ways to accomplish that. My question is more general than that -- about the efficiency of the LINQ Any method vs. the For Each loop approach.

Also, I have reviewed What is the Efficiency and Performance of LINQ and Lambda Expression in .Net? and Find an item in List by LINQ?, among other resources, and they don't answer my question, and I wasn't able to find anything that does.

Community
  • 1
  • 1
rory.ap
  • 34,009
  • 10
  • 83
  • 174
  • Please explain the down vote. – rory.ap Dec 03 '14 at 15:47
  • possible duplicate of [Performance of LINQ Any vs FirstOrDefault != null](http://stackoverflow.com/questions/8339988/performance-of-linq-any-vs-firstordefault-null) – Daniel A. White Dec 03 '14 at 15:47
  • Down votes are if "question does not show research effort, is unclear, or is not useful". Is that true? – rory.ap Dec 03 '14 at 15:48
  • 3
    Nah, downvote isn't justified. – Recipe Dec 03 '14 at 15:49
  • Always with the "drive by down-voters". Makes SO so frustrating to use. – rory.ap Dec 03 '14 at 15:50
  • It is always a joy to link this enlightened article [Which is Faster?](http://ericlippert.com/2012/12/17/performance-rant/). Well if you do your test you'll discover that they are pretty identical with a negligible advantage for the foreach loop – Steve Dec 03 '14 at 15:56

3 Answers3

2

Enumerable.Any is implemented as:

public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
    if (source == null) throw Error.ArgumentNull("source");
    if (predicate == null) throw Error.ArgumentNull("predicate");
    foreach (TSource element in source) {
        if (predicate(element)) return true;
    }
    return false;
}

So, when the item is found it will break out.

Apart from that, you should use String.Equals Method (String, String, StringComparison) overload for comparing string for equality ignoring case. String.Compare is more useful for ordering.

Habib
  • 219,104
  • 29
  • 407
  • 436
1

They are absolutely the same. The implementation of Any() will short circuit as soon as it finds a single matching element.

From the documentation:

The enumeration of source is stopped as soon as the result can be determined.

  • Thanks Will. The documentation doesn't say anything about the efficiency of `Any()`, i.e. O(1), O(n). I'm assuming O(n), but still wondering. – rory.ap Dec 03 '14 at 15:55
  • @roryap it's always O(n) if no matches exist (worst case). It simply rolls through all elements until it finds the first match. If the first match is the first element, it's O(1) (best case). –  Dec 03 '14 at 16:34
1

Decompile the Any method to see what it does...

foreach (TSource source1 in source)
{
    if (predicate(source1))
        return true;
}
return false;

You can see that this is equivalent to the For Each code you posted.

Chris McAtackney
  • 5,192
  • 8
  • 45
  • 69