Monday, 22 April 2013

C# Wish List: yield for Collections

I remembered a new C# feature I want today. If you're familiar with 'yield', it's a great keyword in C# used in iterator blocks. eg:

 // Ignoring that there would be much simpler ways to do this anyway.  
 public static IEnumerable<int> GetEvens(IEnumerable<int> numbers)  
 {  
   foreach (var number in numbers)  
   {  
     if (number % 2 == 0)  
     {  
       yield return number;  
     }  
   }  
 }  

Using yield will also result in lazy evaluation as demonstrated here, when using the method above:

 static void Main(string[] args)  
 {  
   var list = Enumerable.Range(1, 10).ToList();  
   var output = GetEvens(list);  
   list.Add(12);  
   list.Add(22);  
   list.Add(32);  
   foreach (var item in output)  
   {  
     Console.WriteLine(item);  
   }  
 }  

Which prints:

 2  
 4  
 6  
 8  
 10  
 12  
 22  
 32  

Which is an awesome feature. However, I often find cases where I'd like to yield the rest of a collection. For instance, in the Combine method of a MergeSort I was implementing, I had this block from where I wanted to get the rest of the right collection (because the left collection was now empty):

 if (leftIndex == left.Count)  
 {  
   foreach (var x in right.Skip(rightIndex))  
   {  
     yield return x;  
   }  
   break;  
 }  

But it would be much nicer if I could yield the collection. In F# you can yield a collection with yield! eg:

 let FooOneToTen =   
   seq { yield! [1..10] }  

Which I suppose in C# would be more like this:

 if (leftIndex == left.Count)  
 {  
   yield! return right.Skip(rightIndex);  
   break;  
 }  

That would improve readability, but would understandably be a very low priority feature.