<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://devlicio.us/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Sergio Pereira : Juicy, Series</title><link>http://devlicio.us/blogs/sergio_pereira/archive/tags/Juicy/Series/default.aspx</link><description>Tags: Juicy, Series</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>Language Envy - C# needs Ranges</title><link>http://devlicio.us/blogs/sergio_pereira/archive/2010/01/02/language-envy-c-needs-ranges.aspx</link><pubDate>Sat, 02 Jan 2010 10:55:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:54862</guid><dc:creator>sergiopereira</dc:creator><slash:comments>14</slash:comments><description>	&lt;p&gt;
		As soon as I started learning Ruby, a few years ago, I got immediately hooked 
		on its &lt;a href="http://ruby-doc.org/core/classes/Range.html"&gt;&lt;code&gt;Range&lt;/code&gt;&lt;/a&gt; class. 
		I could not believe I had been programming in .NET without them for so long.
	&lt;/p&gt;

	&lt;p&gt;
		I like to think of range objects as the specification for a &lt;code&gt;for&lt;/code&gt;
		loop, packaged in an object that can be passed around. That&amp;#39;s not the whole story, though.
		Ranges also represent sequences or intervals, which can be queried for intersection or
		containment. See the following Ruby sample code.
	&lt;/p&gt;

		&lt;pre name="code" class="ruby:nogutter"&gt;#declare a Range object
summer_months = 6..9
#enumerate it
summer_months.each {|m| puts &amp;quot;#{Date.new(2000, m, 1).strftime(&amp;#39;%B&amp;#39;)} is a Summer month.&amp;quot; }
#other handy features
summer_months.include? 7 # ==&amp;gt; true
summer_months.to_a # ==&amp;gt; [6, 7, 8, 9]  (converted to array)&lt;/pre&gt;


	&lt;h3&gt;I needed that in C#&lt;/h3&gt;
	&lt;p&gt;
		That was back when the CLR 2.0 was just about to be released and I ended up
		writing my own Range&lt;/code&gt; class. I have used this class in a handful of
		projects since then and I&amp;#39;m still surprised that we don&amp;#39;t have it in the
		standard .NET class library. The closest thing I&amp;#39;m aware of is the method
		&lt;a href="http://msdn.microsoft.com/en-us/library/system.linq.enumerable.range.aspx"&gt;&lt;code&gt;System.Linq.Enumerable.Range(int, int)&lt;/code&gt;&lt;/a&gt;,
		which is rather limited (it only enumerates integers one by one).
	&lt;/p&gt;

	&lt;p&gt;
		Here&amp;#39;s the code that I came up with, which has served me well for many years. First 
		an abstract base class. I&amp;#39;ll omit parts of the code for brevity but I&amp;#39;ll give you 
		a link for the complete source at the end.
	&lt;/p&gt;

	&lt;pre name="code" class="csharp:nogutter"&gt;public abstract class RangeBase&amp;lt;T&amp;gt; : IEnumerable&amp;lt;T&amp;gt; where T : IComparable
{
  public T Start { get; set; }
  public T End { get; set; }

  protected RangeBase(T start, T end)
  {
    // ... snip ...
  }

  protected abstract T GetNextItem(T currentItem);

  public IEnumerator&amp;lt;T&amp;gt; GetEnumerator()
  {
    T item = Start;

    while (true)
    {
      if (item.CompareTo(End) &amp;gt; 0)
        break;

      yield return item;

      item = GetNextItem(item);
    }
  }


  IEnumerator IEnumerable.GetEnumerator()
  {
    return GetEnumerator();
  }

  public bool Intersects(RangeBase&amp;lt;T&amp;gt; otherRange)
  {
    // ... snip ...
  }

  public bool Contains(RangeBase&amp;lt;T&amp;gt; otherRange)
  {
    // ... snip ...
  }

  public bool Contains(T element)
  {
    return (Start.CompareTo(element) &amp;lt;= 0) &amp;amp;&amp;amp; (End.CompareTo(element) &amp;gt;= 0);
  }
}&lt;/pre&gt;

	&lt;p&gt;
		There&amp;#39;s also a generic concrete type and a bunch of the more common
		implementations for convenience.
	&lt;/p&gt;

	&lt;pre name="code" class="csharp:nogutter"&gt;public class Range&amp;lt;T&amp;gt; : RangeBase&amp;lt;T&amp;gt; where T : IComparable
{
  public Func&amp;lt;T, T&amp;gt; GetNext { get; private set; }

  public Range(T start, T end, Func&amp;lt;T, T&amp;gt; getNext)
    : base(start, end)
  {
    GetNext = getNext;
  }

  protected override T GetNextItem(T currentItem)
  {
    return GetNext(currentItem);
  }
}

public class Int32Range : RangeBase&amp;lt;int&amp;gt;
{
  public Int32Range(int start, int end) : base(start, end){}
  protected override int GetNextItem(int currentItem)
  {
    return currentItem + 1;
  }
}

public class Int64Range : RangeBase&amp;lt;long&amp;gt; { /* ... snip ... */ }
public class DayRange : RangeBase&amp;lt;DateTime&amp;gt; { /* ... snip ... */ }
public class HourRange : RangeBase&amp;lt;DateTime&amp;gt; { /* ... snip ... */ }
//...etc...&lt;/pre&gt;


	&lt;h3&gt;Coding with Ranges&lt;/h3&gt;
	&lt;p&gt;
		With the above classes I can write code that is similar in functionality to the
		Ruby version.
	&lt;/p&gt;
	&lt;pre name="code" class="csharp:nogutter"&gt;//declare a range of numbers
var summerMonths = new Int32Range(6, 9);
//enumerate it
foreach(var m in summerMonths) 
  Console.WriteLine(new DateTime(2000, m, 1).ToString(&amp;quot;MMMM&amp;quot;) + &amp;quot; is a Summer month.&amp;quot;);
//other handy features
summerMonths.Contains(7); // ==&amp;gt; true
summerMonths.Contains(new Int32Range(7, 8)); // ==&amp;gt; true
summerMonths.ToArray(); // ==&amp;gt; [6, 7, 8, 9]  (using LINQ extensions)&lt;/pre&gt;

	&lt;p&gt;
		We can also use the generic &lt;code&gt;Range&lt;/code&gt; type to create less orthodox
		iterations, like a sequence of dates that repeat &lt;i&gt;every other week&lt;/i&gt;:
	&lt;/p&gt;

&lt;pre name="code" class="csharp:nogutter"&gt;var startDate = new DateTime(2010, 1, 1);
var endDate = startDate.AddMonths(3);
var appointmentDates = new Range&amp;lt;DateTime&amp;gt;(startDate, endDate, d =&amp;gt; d.AddDays(14));
appointmentDates.ToArray(); 
// ==&amp;gt; [ 1/1/2010, 1/15/2010, 1/29/2010, 
//          2/12/2010, 2/26/2010, 3/12/2010, 3/26/2010 ]&lt;/pre&gt;

	&lt;p&gt;
		The complete source for these classes and even some unit tests can be found
		&lt;a href="http://github.com/sergiopereira/juicy/blob/master/src/Juicy.Core/Ranges.cs"&gt;here&lt;/a&gt;.
	&lt;/p&gt;

	&lt;h3&gt;Other implementations&lt;/h3&gt;
	&lt;p&gt;
		Of course I was not the first to implement a Range class in C#. A quick search
		yielded at least a 
		&lt;a href="http://www.pluralsight.com/community/blogs/dbox/archive/2005/04/24/7690.aspx"&gt;couple&lt;/a&gt;
		of &lt;a href="http://andyclymer.blogspot.com/2009/03/ruby-ranges-in-net.html"&gt;articles&lt;/a&gt; with
		different approaches to the same goal.
	&lt;/p&gt;
 &lt;p&gt;Another indication that ranges are a popular data structure is the fact that F# has them too.
With luck we will see ranges in a future version of the .NET framework. Oh, 
and since we are wishing for things. let&amp;#39;s hope they introduce range literals in C# at that same time.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=54862" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/sergio_pereira/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/sergio_pereira/archive/tags/Ruby/default.aspx">Ruby</category><category domain="http://devlicio.us/blogs/sergio_pereira/archive/tags/Series/default.aspx">Series</category><category domain="http://devlicio.us/blogs/sergio_pereira/archive/tags/Language-Envy/default.aspx">Language-Envy</category><category domain="http://devlicio.us/blogs/sergio_pereira/archive/tags/Juicy/default.aspx">Juicy</category></item></channel></rss>