Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a good source that gives an overview of linq optimizations?

Tags:

c#

.net

linq

Linq does a lot of clever things such as returning the result of the Count-property using the Count() method on a IList. Is there a good source that gives an overview of this optimizations?

It would be very interesting because as before I knew the above, I never used Count() and thus often returned a List<T> than only an IEnumerable<T> because i knew that the caller will need need often the instance-count of the list.

But having in mind that Count() does not really count the instances contained in the IEnumerable<T> but returns the result of the Count-property from the returned List and therefore not loosing performance occasioned me to change a lot of my returning types from a List to IEnumerable<T>.

like image 207
HCL Avatar asked Jul 16 '10 10:07

HCL


2 Answers

Try the .NET Reflector. It's a great tool for browsing class libraries, it has a powerful decompiler which let's you view the source code pretty much as it was written.

e.g. The Count() extension method is implemented like this

if (source == null)
{
    throw Error.ArgumentNull("source");
}
ICollection<TSource> is2 = source as ICollection<TSource>;
if (is2 != null)
{
    return is2.Count;
}
ICollection is3 = source as ICollection;
if (is3 != null)
{
    return is3.Count;
}
int num = 0;
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
    while (enumerator.MoveNext())
    {
        num++;
    }
}
return num;

At the off chance that the source does not implement the collection interface you'll have to count to get the actual acount. Browsing the code this way is a great way to learn.

like image 97
John Leidegren Avatar answered Nov 02 '22 07:11

John Leidegren


Current optimisations that I'm aware of:

  • Count uses the Count property if the sequence implements ICollection<T> and a predicate isn't used. (In .NET 4 Count is also optimised for the non-generic ICollection.)

  • ElementAt/ElementAtOrDefault access by index if the sequence implements IList<T>.

  • Last/LastOrDefault access by index if the sequence implements IList<T> and a predicate isn't used.

  • ToArray/ToList use the Count property to allocate memory more efficiently if the sequence implements ICollection<T>. (But neither of them optimise for ICollection.)

Optimisations that could be there but aren't:

  • Last/LastOrDefault don't optimise in the case where a predicate is used. There's no reason why they couldn't optimise for IList<T>, iterating backwards through the list and accessing each element by index.

  • SequenceEqual could optimise for ICollection<T> and ICollection, using the Count property to determine if the lists are the same length and breaking out early if they're not.

  • Skip could optimise for IList<T>, accessing the elements by index and starting directly at index n rather than iterating and discarding the first n elements.

  • ToArray/ToList could also optimise for ICollection, using the Count property to allocate memory more efficiently.

  • ToDictionary could optimise for ICollection<T> and ICollection, using the Count property to allocate memory more efficently.

like image 6
LukeH Avatar answered Nov 02 '22 07:11

LukeH