Hooked on LINQ

Hooked on LINQ - Developers' Wiki
for .NET Language Integrated Query

Companion book for this site
LINQ to Objects Using C# 4.0:
Using and Extending LINQ to Objects and Parallel LINQ (PLINQ)
Quick Search

Advanced Search »
The Between operator is a sample Sequence operator that returns elements after a StartPredicate has been satisfied, until an End Predicate is satisfied. It is written as a sample and the operator could be implemented in alternative ways using the SkipWhile operator and the TakeWhile operators using a normal query.

The only information we have on the source sequence is that it is IEnumerable (being that is the type our extension method is targeting), so we know we can foreach over the source elements, or manually use our own iteration block.

The code behind this operator shows remarkable similarity to the Sequence.cs source code supplied by Microsoft as part of the MAY 2006 LINQ CTP. This is intentional, the patterns shown in the Standard Query Operators should be the basis for all of our operators to ensure a consistent developer experience when using them. We should throw similar exceptions, and use the delegate prorotypes that all the other operators use.

Back to Writing Operators

Edit

The Code

using System; using System.Collections.Generic; using System.Text; using System.Query;

namespace Aspiring.Query { public static class BetweenExtensions { public static IEnumerable Between( this IEnumerable source, Func endPredicate) {

if (source == null) throw Error.ArgumentNull("source"); if (endPredicate == null) throw Error.ArgumentNull("endPredicate"); return BetweenIterator(source, b => true, endPredicate); }

public static IEnumerable Between( this IEnumerable source, Func startPredicate, Func endPredicate) {

if (source == null) throw Error.ArgumentNull("source"); if (startPredicate == null) throw Error.ArgumentNull("startPredicate"); if (endPredicate == null) throw Error.ArgumentNull("endPredicate"); return BetweenIterator(source, startPredicate, endPredicate); }

static IEnumerable BetweenIterator( IEnumerable source, Func startPredicate, Func endPredicate) {

bool foundStart = false;

foreach (T element in source) { if (startPredicate(element)) foundStart = true;

if (foundStart) if (!endPredicate(element)) yield return element; else yield break; } }

class Error { internal static Exception ArgumentNull(string paramName) { return new ArgumentNullException(paramName); } } } }

Edit

The Unit Tests

using System; using System.Collections.Generic; using System.Text; using System.Query; using NUnit.Framework; using Aspiring.Query;

namespace Aspiring.Query.UnitTests { TestFixture public class BetweenTests { Test ExpectedException("System.ArgumentNullException") public void BetweenEndPredicateNullSourceTest() { int[] values = null; int[] result = values.Between(end => true).ToArray(); }

Test ExpectedException("System.ArgumentNullException") public void BetweenEndPredicateNullPredicateTest() { int[] values = null; int[] result = values.Between(null).ToArray(); }

Test ExpectedException("System.ArgumentNullException") public void BetweenStartAndEndPredicateNullSourceTest() { int[] values = null; int[] result = values.Between(start => true, end => true).ToArray(); }

Test ExpectedException("System.ArgumentNullException") public void BetweenStartAndEndPredicateNullPredicateTest() { int[] values = null; int[] result = values.Between(null, null).ToArray(); }

Test public void BetweenStartAndEndIntTest() { int[] values = Sequence.Range(0,20).ToArray(); int[] result = values.Between(start => start > 4, end => end > 9).ToArray(); Assert.AreEqual(5,result.Count(), "incorrect number returned");

for (int i = 0; i < result.Count(); i++) Assert.AreEqual(i+5, resulti); } } }

If you would like to comment on this page, click on the Discuss button located on the top-right of each page. Feel free to edit any mistakes or omissions you find. If you have an objection or find in-appropriate content then contact the administrator. This website is not affiliated with Microsoft®, all content and opinions are those of the specific author and some advice, solutions and article may contain unintentional errors - please use care. Other websites by this author: Focused Objective, Geek Speak Decoded.