 <p>Further to <a href="http://stackoverflow.com/q/8214635/55847">Gabe's answer</a>, I can confirm that the difference appears to be caused by the cost of re-constructing the delegate for every call to <code>GetPointData</code>.</p> <p>If I add a single line to the <code>GetPointData</code> method in your <code>IterationRangeLookupSingle</code> class then it slows right down to the same crawling pace as <code>LinqRangeLookupSingle</code>. Try it:</p> <pre><code>// in IterationRangeLookupSingle&lt;TItem, TKey&gt; public TItem GetPointData(DateTime point) { // just a single line, this delegate is never used Func&lt;TItem, bool&gt; dummy = i =&gt; i.IsWithinRange(point); // the rest of the method remains exactly the same as before // ... } </code></pre> <p>(I'm not sure why the compiler and/or jitter can't just ignore the superfluous delegate that I added above. Obviously, the delegate <em>is</em> necessary in your <code>LinqRangeLookupSingle</code> class.)</p> <p>One possible workaround is to compose the predicate in <code>LinqRangeLookupSingle</code> so that <code>point</code> is passed to it as an argument. This means that the delegate only needs to be constructed <em>once</em>, not every time the <code>GetPointData</code> method is called. For example, the following change will speed up the LINQ version so that it's pretty much comparable with the <code>foreach</code> version:</p> <pre><code>// in LinqRangeLookupSingle&lt;TItem, TKey&gt; public TItem GetPointData(DateTime point) { Func&lt;DateTime, Func&lt;TItem, bool&gt;&gt; builder = x =&gt; y =&gt; y.IsWithinRange(x); Func&lt;TItem, bool&gt; predicate = builder(point); return this.items.FirstOrDefault(predicate); } </code></pre>