Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yield Return Many?

Tags:

c#

I find myself foreach-ing over IEnumerables a lot just so that I can return each result. Is there a way to compress something like this

foreach (var subSelector in subSelectors) {     foreach (var node in FindSingle(context, subSelector))         yield return node; }  

To remove the inner foreach?

like image 836
mpen Avatar asked Oct 03 '10 23:10

mpen


People also ask

What is yield return?

The yield is the income the investment returns over time, typically expressed as a percentage, while the return is the amount that was gained or lost on an investment over time, usually expressed as a dollar value.

When should you use yield return?

You use a yield return statement to return each element one at a time. The sequence returned from an iterator method can be consumed by using a foreach statement or LINQ query. Each iteration of the foreach loop calls the iterator method.

What is yield break in C#?

It specifies that an iterator has come to an end. You can think of yield break as a return statement which does not return a value. For example, if you define a function as an iterator, the body of the function may look like this: for (int i = 0; i < 5; i++) { yield return i; } Console.

What are the two keywords required in an iterator method or property used to return one element at a time?

In the iterator block, the yield keyword is used together with the return keyword to provide a value to the enumerator object. This is the value that is returned, for example, in each loop of a foreach statement. The yield keyword is also used with break to signal the end of iteration."


2 Answers

This is a somewhat frequently requested feature that C# does not support. See this Connect item for details:

http://connect.microsoft.com/VisualStudio/feedback/details/256934/yield-return-to-also-yield-collections

The proposed syntax is usually something like:

public static IEnumerable<T> PreorderTraversal<T>(this BinaryTree<T> root) {     if (root == null) yield break;     yield return root.Item;     yield foreach root.Left.PreorderTraversal();     yield foreach root.Right.PreorderTraversal(); } 

If you are interested in playing with a C#-like language that supports this feature, take a look at Cω:

http://research.microsoft.com/en-us/um/cambridge/projects/comega/

You might also want to read this paper on the feature by the implementors of Cω:

http://research.microsoft.com/en-us/projects/specsharp/iterators.pdf

If you're interested in a non-C#-like language that supports this feature, take a look at the "yield!" feature of F#. (I just love that the name of the feature is "yield!")

Even if you are not interested in the theoretical stuff, it sounds like you face this situation as a practical problem. You should also read Wes Dyer's article on techniques for efficiently doing this sort of nested iteration without "yield foreach":

http://blogs.msdn.com/b/wesdyer/archive/2007/03/23/all-about-iterators.aspx

like image 161
Eric Lippert Avatar answered Sep 28 '22 03:09

Eric Lippert


No, there isn't, unless you completely replace every yield return with a single return statement using LINQ.

For example:

return someSet     .Concat(someOtherSet.SelectMany(s => FindSingle(context, s)); 
like image 44
SLaks Avatar answered Sep 28 '22 05:09

SLaks