Saturday, April 9, 2011

When not to use Count in C#

During my daily development I have to deal with IEnumerables quite often. Old habits takes time to go but now I try to use LINQ to Objects as much as possible in my code while dealing with IEnumerables. LINQ to Objects or LINQ in general is one of the best thing that have been added in C# in past couple of years in my personal opinion.

As I said, old habits take time to go, one habit which I am trying to get rid of these days is to avoid using Count property. At countless places in my code I have used this piece of code and I am sure many of you would have done same

   1:  if(SomeCollection.Count == 0)
   2:      DoSomething();
   3:  else
   4:      DoSomethingElse();
In above piece of code you just want to know whether the collection contains any item or not and based on that you will perform some operation. Problem is that to find this yes or no you are traversing the whole list when you use Count. Let's say your collection contain 1000 element. You are traversing whole list just to find out whether there is any item in the list or not. Which doesn't make any sense at all. Instead what we can use is a simple LINQ method 'Any'.

   1:  if(SomeCollection.Any())
   2:      DoSomething();
   3:  else
   4:      DoSomethingElse();
Use of 'Any' will make your code much faster because instead of traversing whole collection 'Any' will return as soon as it finds that there is an element in your collection or even in case there isn't any at all. This is just one example I am sure there will be many more examples in my daily development which can be simplified using LINQ to Objects.

Note that "if you are starting with something that has a .Length or .Count (such as ICollection<T>, IList<T>, List<T>, etc) - then this will be the fastest option, since it doesn't need to go through the GetEnumerator()/MoveNext()/Dispose() sequence required by Any() to check for a non-empty IEnumerable<T> sequence. For just IEnumerable<T>, then Any() will generally be quicker, as it only has to look at one iteration. However, note that the LINQ-to-Objects implementation of Count() does check for ICollection<T> (using .Count as an optimisation) - so if your underlying data-source is directly a list/collection, there won't be a huge difference. In general with IEnumerable<T> : stick with Any()." Taken this paragraph from here

2 comments:

  1. Hi Haris,

    What type is SomeCollection? I don't know of any lists/arrays in .NET that have to iterate over to get the count. If it's an IEnumerable and does not implement ICollection, then sure. But your posts is misleading in that regard.

    ReplyDelete
  2. @Joe, Thanks for pointing it out. You are right it only makes sense to use Any instead of Count if you are dealing with IEnumerable. I should have focused more on IEnumerable rather than mentioning collections in general. I have updated the post for more clarity

    ReplyDelete