Reimplementing LINQ to Objects: Part 26a – IOrderedEnumerable

Implementing OrderBy/OrderByDescending/ThenBy/ThenByDescending isn’t too bad, once you understand how the pattern works, but that’s a slight conceptual leap. I’ll take it one step at a time, first introducing some extra infrastructure (both public and internal), then implementing it simply and slowly, and finally optimizing it somewhat. The sorting features of LINQ As a query language, it’s natural that LINQ allows you to sort sequences. Of course, collections have had the ability to sort their contents since v1.0 but LINQ is different in various ways: It expects you’ll usually want to sort via projections, rather than on a "natural" comparison of … Continue reading Reimplementing LINQ to Objects: Part 26a – IOrderedEnumerable

Reimplementing LINQ to Objects: Part 25 – ToDictionary

This one ended up being genuinely easy to implement, although with lots of tests for different situations. What is it? ToDictionary has four overloads which look remarkably similar to the ones we used for ToLookup: public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(     this IEnumerable<TSource> source,     Func<TSource, TKey> keySelector) public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(     this IEnumerable<TSource> source,     Func<TSource, TKey> keySelector,     Func<TSource, TElement> elementSelector) public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(     this IEnumerable<TSource> source,     Func<TSource, TKey> keySelector,     IEqualityComparer<TKey> comparer)          public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(     this IEnumerable<TSource> source,     Func<TSource, TKey> keySelector,     Func<TSource, TElement> … Continue reading Reimplementing LINQ to Objects: Part 25 – ToDictionary

Reimplementing LINQ to Objects: Part 24 – ToArray

This really is a simple one. So simple I might even find the energy to implement ToDictionary as well tonight… we’ll see. (EDIT: Oops. It became slightly less simple in the end, as I came up with the third implementation. Oh well.) What is it? ToArray is basically the equivalent of ToList, but producing an array instead of a list. It has a single signature: public static TSource[] ToArray<TSource>(this IEnumerable<TSource> source) Just to recap: It’s another extension method, which is useful when we want to use type inference. It uses immediate execution – nothing is deferred, and the entire sequence is … Continue reading Reimplementing LINQ to Objects: Part 24 – ToArray

Reimplementing LINQ to Objects: Part 23 – Take/Skip/TakeWhile/SkipWhile

I genuinely expected these operators to be simple. At the time of this writing, I’m onto my third implementation of SkipWhile, struggling to find code which obviously expresses what’s going on. I find it interesting how the simplest sounding operators sometimes end up being trickier to implement than one might think. What are they? Take, TakeWhile, Skip and SkipWhile form a natural group of operators. Together they are known as the partitioning operators. Here are the signatures: public static IEnumerable<TSource> Take<TSource>(     this IEnumerable<TSource> source,     int count) public static IEnumerable<TSource> TakeWhile<TSource>(     this IEnumerable<TSource> source,     Func<TSource, bool> predicate) public static IEnumerable<TSource> … Continue reading Reimplementing LINQ to Objects: Part 23 – Take/Skip/TakeWhile/SkipWhile

Reimplementing LINQ to Objects: Part 22 – GroupJoin

Another operator that was decidedly easy to implement – partly as I was able to just adapt everything from Join, including the tests. 15 minutes for tests + implementation… and no doubt considerably long writing it up. What is it? After the complexity of GroupBy, GroupJoin has a refreshingly small list of overloads: public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(     this IEnumerable<TOuter> outer,     IEnumerable<TInner> inner,     Func<TOuter, TKey> outerKeySelector,     Func<TInner, TKey> innerKeySelector,     Func<TOuter, IEnumerable<TInner>, TResult> resultSelector) public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(     this IEnumerable<TOuter> outer,     IEnumerable<TInner> inner,     Func<TOuter, TKey> outerKeySelector,     Func<TInner, TKey> innerKeySelector, … Continue reading Reimplementing LINQ to Objects: Part 22 – GroupJoin

Reimplementing LINQ to Objects: Part 21 – GroupBy

Okay, after the brief hiatus earlier, we’re ready to group sequences. What is it? GroupBy has eight overloads, using up to four type parameters and up to five normal parameters. Those of a sensitive disposition may wish to turn away now: public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(     this IEnumerable<TSource> source,     Func<TSource, TKey> keySelector) public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(     this IEnumerable<TSource> source,     Func<TSource, TKey> keySelector,     IEqualityComparer<TKey> comparer) public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(     this IEnumerable<TSource> source,     Func<TSource, TKey> keySelector,     Func<TSource, TElement> elementSelector) public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(     this IEnumerable<TSource> source,     Func<TSource, … Continue reading Reimplementing LINQ to Objects: Part 21 – GroupBy

Reimplementing LINQ to Objects: Part 20 – ToList

This morning I started writing the tests for GroupBy, prior to implementing it. That turned out to be a pain – really I wanted an easy way of getting at each element of the result (i.e. each result group). If only I had the ability to convert an arbitrary sequence into a query… I needed ToList. So, we enter a fairly brief diversion. What is it? ToList has a single, simple overload: public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) Fairly obviously, ToList converts the source sequence into a list. Some points to note: The signature specifies List<T>, not just IList<T>. Of course … Continue reading Reimplementing LINQ to Objects: Part 20 – ToList