Update: The post was lost by accident, I added it again.
I’ve used the reflector a couple of times to check whether the Enumerable class which provide all the IEnumerable extensions utilizes things taking the actual type into mind.
Let’s examine the extension method “Count” –
I liked what they did here. They first try and cast it to ICollection, if it passed they simply return the count property. Otherwise they would do what you would do – iterate over the collection and return the iteration counter.
I was thrilled to see that but I was disappointed to see the implementation for “ToList”.
Let’s look at the following example –
– I got a business entity called “Foo”.
– I got an interface for providers to implement that return IEnumerable<Foo>
– I got a service operation which returns a List<Foo>
In the solution, the service gets a provider instance (let’s assume from a factory or something, doesn’t matter) and returns the provider.GetFoos().ToList()
Remember – GetFoos() in the provider returns IEnumrable<Foo>.
A word about ToList implementation –
ToList doesn’t check the runtime type of the enumerable source. It simply returns a new list and copies the source items to the new one.
In a case where I have a provider which returns an actual List<Foo>, the “ToList” will still create a new list instance and copy over the items!
I created a new extension to help me around with it –
internal static List<T> AsList<T>(this IEnumerable<T> source)
return list as List<T> ?? source.ToList();
internal static T AsArray<T>(this IEnumerable<T> source)
return list as T ?? source.ToArray();
Just for the sake of the demonstration, you can download the source attached to see the improvement in action.
The sample shows the improvement for collection with 1,000,000 items (feel free to change it) where there is ~40-200miliseconds improvement between the two.
Note: It it true that the differences are not significant when the collection is small.
However, anything that is made in minimal effort (calling AsList instead of ToList) to save even a small fraction of time is a good thing to keep in mind.