views:

340

answers:

7

In a recent interview I was asked what the difference between .Any() and .Length > 0 was and why I would use either when testing to see if a collection had elements.

This threw me a little as it seems a little obvious but feel I may be missing something.

I suggested that you use .Length when you simply need to know that a collection has elements and .Any() when you wish to filter the results.

Presumably .Any() takes a performance hit too as it has to do a loop / query internally.

+9  A: 

Length only exists for some collection types such as Array.

Any is an extension method that can be used with any collection that implements IEnumerable<T>.

If Length is present then you can use it, otherwise use Any.


Presumably .Any() takes a performance hit too as it has to do a loop / query internally.

Enumerable.Any does not loop. It fetches an iterator and checks if MoveNext returns true. Here is the source code from .NET Reflector.

public static bool Any<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        if (enumerator.MoveNext())
        {
            return true;
        }
    }
    return false;
}
Mark Byers
There's also an `IQueryable<T>` version, but I'm not which which the OP is talking about, maybe both. Edit: by collection I'm guessing you're right, just linq-to-entities
Nick Craver
Good explanation thanks
Chris
+1  A: 

Length is a property of array types, while Any() is an extension method of Enumerable. Therefore, you can use Length only when working with arrays. When working with more abstract types (IEnumerable<T>), you can use Any().

Steven
A: 

I think this is a more general question of what to choose if we have 2 way to express something. In does situation I would suggest the statement: "Be specific" quote from Peter Norvig in his book PAIP

Be specific mean use what best describe what your are doing. Thus what you want to say is something like:

collection.isEmpty()

If you don't have such construct I will choose the common idiom that the communities used. For me .Length > 0 is not the best one since it impose that you can size the object. Suppose your implement infinite list. .Lenght would obviously not work.

mathk
A: 

.Length... System.Array .Any ... IEnumerable (extension method).

I would prefer using "length" whenever i can find it. Property is anyhow light-weight than any method call.

Though, implementation of "Any" won't be doing anything more than the below mentioned code.

 private static bool Any<T>(this IEnumerable<T> items)
        {
            return items!=null && items.GetEnumerator().MoveNext();
        }

Also, A better question could have been a difference beterrn ".Count" and ".Length", what say :).

Amby
Interesting... can you explain : "Property is anyhow light-weight than any method call. "
David B
@David: Property is generally a get/set over a field (an in-memory value) while a method has freedom to perform all possible computations. I would always rely on a call to a get_Property than a method call. ( eg: obj.ComputedValue Vs ComputeValue() )
Amby
So it is merely the convention or guidelines, not any technical reason. A property could be implemented in violation of the convention (for example, the property could call the method).
David B
A: 

Sounds quite similar to this Stackoverflow question about difference between .Count and .Any for checking for existence of a result: http://stackoverflow.com/questions/2540220/check-for-existence-of-a-result-in-linq-to-xml/2540302#2540302

In that case it is better to use Any then Count, as Count will iterate all elements of an IEnumerable

Kris C
This is not true, `.Count()` **will** use the `.Count` (which gets `.Length` on an Array for example) property on an `ICollection` (generic or not), `.Any()` **won't** use this and will enumerate, you can fire up reflector to see this, still true in .Net 4. An `IQueryable<T>` is a different story, but on `IEnumerable<T>` this doesn't change.
Nick Craver
That's interesting - I'd interpreted the following as being that Count will enumerate and and Any will not: http://rapidapplicationdevelopment.blogspot.com/2009/07/ienumerablecount-is-code-smell.html
Kris C
@Nick: `Any()` (at least the overload that takes no arguments) will enumerate over *one* item. `Count()`, if the underlying `IEnumerable<T>` is not an `ICollection<T>`, will enumerate over *all* items. For this reason it makes much more sense to use `Any()` than `Count() > 0` if the collection type is not known.
Dan Tao
@Dan - That's not absolute though, opening an iterator itself may be very expensive, so checking `.Count` vs getting the iterator and grabbing ons is an unknown cost difference. In any case, for the purposes of an interview, won't you know which collection you're dealing with *most* of the time? If it's `ICollection` every time and you use `.Any()` it's more expensive. I think your qualifier of "if the collection type is not known" is the key here, unless you're writing a framework for others, I think you *do* know this most of the time.
Nick Craver
@Nick: I think the "unless you're writing a framework for others" part makes this possibility sound rarer than it is. You might be writing a general-purpose method or library; it doesn't have to be an entire framework. That said, you're right that the cost of opening an iterator is unknown; but so is the cost of accessing the `Count` property of some 3rd party `ICollection<T>`. There are always going to be unknowns; in the case of an `IEnumerable<T>` of unknown type, to *me*, `Any()` seems like a much better educated guess.
Dan Tao
@Nick: Anyway, it seems to me the whole point of an interview question like this would be to distinguish whether the developer understood that `Count()` could potentially be an O(n) operation (though the OP did say `Length`...). Clearly, as long as he/she demonstrated understanding of these matters, the interviewer ought to have been satisfied.
Dan Tao
@Dan - All good points, most of what I write is for my own or local consumption so the unknown type is comparatively rare, I see how that's easily not the case though. I *definitely* agree on the interviewer piece, him knowing the difference and possible costs of each approach *should* be the entire point...unfortunately for me, a lot of programmers we've interviewed lately don't have a clue :-/
Nick Craver
A: 

We know that .Length is only used for Arrays and .Any() is used for collections of IEnumerable.

You can swap .Count for .Length and you have the same question for working with collections of IEnumberable

Both .Any() and .Count perform a null check before beginning an enumerator. So with regards to performance they are the same.

As for the array lets assume we have the following line:

int[] foo = new int[10];

Here foo.Length is 10. While this is correct it may not be the answer your looking for because we haven't added anything to the array yet. If foo is null it will throw an exception.

hipplar
+6  A: 

I'm guessing the interviewer may have meant to ask about checking Any() versus Count() > 0 (as opposed to Length > 0).

Basically, here's the deal.

Any() will effectively try to determine if a collection has any members by enumerating over a single item. (There is an overload to check for a given criterion using a Func<T, bool>, but I'm guessing the interviewer was referring to the version of Any() that takes no arguments.) This makes it O(1).

Count() will check for a Length or Count property (from a T[] or an ICollection or ICollection<T>) first. This would generally be O(1). If that isn't available, however, it will count the items in a collection by enumerating over the entire thing. This would be O(n).

A Count or Length property, if available, would most likely be O(1) just like Any(), and would probably perform better as it would require no enumerating at all. But the Count() extension method does not ensure this. Therefore it is sometimes O(1), sometimes O(n).

Presumably, if you're dealing with a nondescript IEnumerable<T> and you don't know whether it implements ICollection<T> or not, you are much better off using Any() than Count() > 0 if your intention is simply to ensure the collection is not empty.

Dan Tao