Need help in terminating deferred execution - c#

The following snippet prints 1 through 10 on the console, but does not terminate until variable 'i' reaches int.MaxValue. TIA for pointing out what I am missing.
class Program
{
public static IEnumerable<int> GetList()
{
int i = 0;
while (i < int.MaxValue)
{
i++;
yield return i;
}
}
static void Main(string[] args)
{
var q = from i in GetList() // keeps calling until i reaches int.MaxValue
where i <= 10
select i;
foreach (int i in q)
Console.WriteLine(i);
}
}

You could try:
var q = GetList ().TakeWhile ((i)=> i <=10);

The query that you defined in Main doesn't know anything about the ordering of your GetList method, and it must check every value of that list with the predicate i <= 10. If you want to stop processing sooner, you will you can use the Take extension method or use the TakeWhile extension method:
foreach (int i in GetList().Take(10))
Console.WriteLine(i);
foreach (int i in GetList().TakeWhile(x => x <= 10))
Console.WriteLine(i);

Your iterators limits are 0 through Int32.MaxValue, so it will process that whole range. Iterators are only smart enough to not pre-iterate the results of the range of data you design it to iterate. However they are not smart enough to know when the code that uses them no longer needs more unless you tell it so (i.e. you break out of a foreach loop.) The only way to allow the iterator to limit itself is to pass in the upper bound to the GetList function:
public static IEnumerable<int> GetList(int upperBound)
{
int i = 0;
while (i < upperBound)
{
i++;
yield return i;
}
}
You could also explicitly tell the iterator that you only wish to iterate the first 10 results:
var numbers = GetList().Take(10);

Consider using the LINQ extension method .Take() with your argument instead of having it in your where clause. More on Take.
var q = from i in GetList().Take(10)
select i;

Related

Implementation of custom iterator does not change one of its parameters

I have this iterator and want it to stop on some condition, thus, there is a 3rd parameter called "condition".
public static IEnumerable<long> Dates(long start, int step, bool condition)
{
var k = start + step;
while (condition)
{
k += step;
yield return k;
}
}
I call it this way :
var i = 0;
foreach (var k in Iterator.Dates(0, 5, i++ < 100))
{
// Here goes infinite loop because (i++ < 100) is always true inside iterator
}
Unfortunately, this parameter does not change inside loop so now it is always true because seems that it gets executed only on the first iteration.
Question : how to check or execute "condition" on each iteration?
Argument is bool, but you need predicate function like this:
public static IEnumerable<long> Dates(long start, int step, Func<bool> condition)
{
var k = start + step;
while (condition())
{
k += step;
yield return k;
}
}
Usage:
var i = 0;
foreach (var k in Dates(0, 5, () => i++ < 100))
{
// Here goes infinite loop because (i++ < 100) is always true inside iterator
}
Comments
() => i++ < 100 is lambda expression similar to boolean function without arguments that returns i++ < 100.
What you want to provide is a piece of functionality, a rule. Instead you have provided a value, and this value is calculated in the expression before the method is called and thus inside the method it is constant, never changes, exactly like you observed.
Instead you need to pass in a delegate, you "delegate" the responsibility of providing the rule to the caller.
A simple delegate type appropriate for this example is Func<T> which is basically defined like this:
public delegate T Func<T>();
This is a delegate that wraps a method that returns a value, without taking any parameters.
Since you want to use the result of this function in a while statement, you need it to return bool.
Here's how you would declare the method:
public static IEnumerable<long> Dates(long start, int step, Func<bool> condition)
{
var k = start + step;
while (condition())
{
k += step;
yield return k;
}
}
Note that you need to change the while expression to call the delegate. Since it wraps a method, to obtain the value from the method you have to call it.
Here's how to call the new method:
var i = 0;
foreach (var k in Iterator.Dates(0, 5, () => i++ < 100))
{
// No longer infinite loop because (i++ < 100) is now evaluated on every iteration
}
This new expression:
() => i++ < 100
is basically the same as writing this:
int i;
bool Func()
{
return i++ < 100;
}
but wrapped in a smaller syntax.
Now, every time the loop runs one iteration, it will call this func, which will increase the value and compare it to 100.

What is the use of the "yield" keyword in C#? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Proper Use of yield return
What is the use of the yield keyword in C#?
I didn't understand it from the MSDN reference... can someone explain it to me please?
I'm going to try and give you an example
Here's the classical way of doing, which fill up a list object and then returns it:
private IEnumerable<int> GetNumbers()
{
var list = new List<int>();
for (var i = 0; i < 10; i++)
{
list.Add(i);
}
return list;
}
the yield keyword returns items one by one like this :
private IEnumerable<int> GetNumbers()
{
for (var i = 0; i < 10; i++)
{
yield return i;
}
}
so imagine the code that calls the GetNumbers function as following:
foreach (int number in GetNumbers())
{
if (number == 5)
{
//do something special...
break;
}
}
without using yield you would have to generate the whole list from 0-10 which is then returned, then iterated over until you find the number 5.
Now thanks to the yield keyword, you will only generate numbers until you reach the one you're looking for and break out the loop.
I don't know if I was clear enough..
my question is, when do I use it? Is there any example out there where I have there is no other choice but using yield? Why did someone feel C# needed another keyword?
The article you linked provided a nice example of when and how it is used.
I hate to quote an article you yourself linked too, but incase it's too long, and you didn't read it.
The yield keyword signals to the compiler that the method in which it appears is an iterator block. The compiler generates a class to implement the behavior that is expressed in the iterator block.
public static System.Collections.IEnumerable Power(int number, int exponent)
{
int counter = 0;
int result = 1;
while (counter++ < exponent)
{
result = result * number;
yield return result;
}
}
In the above example, the yield statement is used inside an iterator block. When the Power method is invoked, it returns an enumerable object that contains the powers of a number. Notice that the return type of the Power method is System.Collections.IEnumerable, an iterator interface type.
So the compiler automatically generates a IEnumerable interfaced based on the things that were yielded during the method's execution.
Here is a simplified example, for the sake of completeness:
public static System.Collections.IEnumerable CountToTen()
{
int counter = 0;
while (counter++ < 10)
{
yield return counter;
}
}
public static Main(string[]...)
{
foreach(var i in CountToTen())
{
Console.WriteLine(i);
}
}

Can an Action/delegate change it's arguments value?

I ran into what was to me an unexpected result when testing a simple ForEach extension method.
ForEach method
public static void ForEach<T>(this IEnumerable<T> list, Action<T> action)
{
if (action == null) throw new ArgumentNullException("action");
foreach (T element in list)
{
action(element);
}
}
Test method
[TestMethod]
public void BasicForEachTest()
{
int[] numbers = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
numbers.ForEach(num =>
{
num = 0;
});
Assert.AreEqual(0, numbers.Sum());
}
Why would numbers.Sum() be equal to 55 and not 0?
num is the copy of the value of the current element you are iterating over. So you are just changing the copy.
What you do is basically this:
foreach(int num in numbers)
{
num = 0;
}
Surely you do not expect this to change the content of the array?
Edit: What you want is this:
for (int i in numbers.Length)
{
numbers[i] = 0;
}
In your specific case you could maintain an index in your ForEach extension method and pass that as second argument to the action and then use it like this:
numbers.ForEachWithIndex((num, index) => numbers[index] = 0);
However in general: Creating Linq style extension methods which modify the collection they are applied to are bad style (IMO). If you write an extension method which cannot be applied to an IEnumerable<T> you should really think hard about it if you really need it (especially when you write with the intention of modifying the collection). You have not much to gain but much to loose (like unexpected side effects). I'm sure there are exceptions but I stick to that rule and it has served me well.
Because num is a copy.
It's as if you were doing this:
int i = numbers[0];
i = 0;
You wouldn't expect that to change numbers[0], would you?
Because int is a value type and is passed to your extension method as a value parameter. Thus a copy of numbers is passed to your ForEach method. The values stored in the numbers array that is initialized in the BasicForEachTest method are never modified.
Check this article by Jon Skeet to read more on value types and value parameters.
I am not claiming that the code in this answer is useful, but (it works and) I think it illustrates what you need in order to make your approach work. The argument must be marked ref. The BCL does not have a delegate type with ref, so just write your own (not inside any class):
public delegate void MyActionRef<T>(ref T arg);
With that, your method becomes:
public static void ForEach2<T>(this T[] list, MyActionRef<T> actionRef)
{
if (actionRef == null)
throw new ArgumentNullException("actionRef");
for (int idx = 0; idx < list.Length; idx++)
{
actionRef(ref list[idx]);
}
}
Now, remember to use the ref keyword in your test method:
numbers.ForEach2((ref int num) =>
{
num = 0;
});
This works because it is OK to pass an array entry ByRef (ref).
If you want to extend IList<> instead, you have to do:
public static void ForEach3<T>(this IList<T> list, MyActionRef<T> actionRef)
{
if (actionRef == null)
throw new ArgumentNullException("actionRef");
for (int idx = 0; idx < list.Count; idx++)
{
var temp = list[idx];
actionRef(ref temp);
list[idx] = temp;
}
}
Hope this helps your understanding.
Note: I had to use for loops. In C#, in foreach (var x in Yyyy) { /* ... */ }, it is not allowed to assign to x (which includes passing x ByRef (with ref or out)) inside the loop body.

Is there an "upto" method in C#?

Here's a bit of code which prints out the squares of the numbers from 0 to 9:
for (int i = 0; i < 10; i++)
Console.WriteLine(i*i);
Doing something from 0 to N by 1 via a for loop is a very common idiom.
Here's an UpTo method which expresses this:
class MathUtil
{
public static void UpTo(int n, Action<int> proc)
{
for (int i = 0; i < n; i++)
proc(i);
}
}
The squares example above is now:
MathUtil.UpTo(10, (i) => Console.WriteLine(i * i));
My question is, does the standard C# library come with something like the above UpTo?
Ideally, I'd like a way to have 'UpTo' be a method on all integer objects. So I could do:
var n = 10;
n.UpTo(...);
Is this possible in C#?
Turn it into an extension method (note the this before the n parameter, which defines the type this method operates on):
static class MathUtil
{
public static void UpTo(this int n, Action<int> proc)
{
for (int i = 0; i < n; i++)
proc(i);
}
}
Usage:
10.UpTo((i) => Console.WriteLine(i * i));
Note: The above method call isn't particularly intuitive though. Remember code is written once and read many times.
Maybe allowing something like below might be slightly better, but to be honest i'd still just write a foreach loop.
0.UpTo(10 /*or 9 maybe*/, (i) => Console.WriteLine(i * i));
If you wanted this, then you could write an extension method like this:
public static void UpTo(this int start, int end, Action<int> proc)
{
for (int i = start; i < end; i++)
proc(i);
}
Change < to <= if you want an inclusive upper bound.
Take a look at LINQ TakeWhile or for your specific case of integers, use Enumerable.Range
Enumerable.Range(1, 10).Select(i => ...);
Arguably you shouldn't be putting an Action on the end there, see comments on ForEach here.
Try this:
public static class IntExtensions
{
public static void UpTo(this int n, Action<int> proc)
{
for (int i = 0; i < n; i++)
proc(i);
}
}
With this you could write
10.UpTo(i => Console.WriteLine(i * i));
The function I wrote is called an extension method.
At design time you notice is not a native function because it has a different icon.
Estension methods are static methods or functions included in a static class and type they work on is the first param on which you must use this keyword.
In IntExtensions class you could write all methods you please; grouping them inside the same static class makes you easy manage them.
wanna do it in one line ? here it goes:
Enumerable.Range(0, 9).Select(i => i * i).ToList().ForEach(j=>Console.WriteLine("%d",j));
Try Enumerable.Range, possibly in combination with Take or TakeWhile:
IEnumerable<int> values = Enumerable.Range(0, 20)
.Take(10); // Not necessary in this example
foreach(var value in values)
{
Console.WriteLine(value);
}
// or ...
foreach(var i in Enumerable.Range(0, 10))
{
Console.WriteLine(i * i);
}
There is a ForEach on List<T> that you could use to get closer syntax to what you want, but I consider it bad form. It takes a pure query/filter/transform syntax, that works in an effectively immutable fashion, and introduces side-effects.
For your future amusement you might want to check out extension methods, IEnumerable<T>, and yield return. A lot of generator-type functionality and interesting syntax becomes possible when you use those three things in combination. Although I would argue that this particular example isn't the best place to use them because the resulting syntax becomes a mess.
Make your method like this in a static class "Extensions" for example:
public static void UpTo(this int n, Action<int> proc)
{
for (var i = 0; i < n; i++)
proc(i);
}
And the usage:
var n = 10;
n.UpTo(i => Console.WriteLine(i * i));
Hope this helps! :)

Some help understanding "yield"

In my everlasting quest to suck less I'm trying to understand the "yield" statement, but I keep encountering the same error.
The body of [someMethod] cannot be an iterator block because
'System.Collections.Generic.List< AClass>' is not an iterator interface type.
This is the code where I got stuck:
foreach (XElement header in headersXml.Root.Elements()){
yield return (ParseHeader(header));
}
What am I doing wrong? Can't I use yield in an iterator? Then what's the point?
In this example it said that List<ProductMixHeader> is not an iterator interface type.
ProductMixHeader is a custom class, but I imagine List is an iterator interface type, no?
--Edit--
Thanks for all the quick answers.
I know this question isn't all that new and the same resources keep popping up.
It turned out I was thinking I could return List<AClass> as a return type, but since List<T> isn't lazy, it cannot. Changing my return type to IEnumerable<T> solved the problem :D
A somewhat related question (not worth opening a new thread): is it worth giving IEnumerable<T> as a return type if I'm sure that 99% of the cases I'm going to go .ToList() anyway? What will the performance implications be?
A method using yield return must be declared as returning one of the following two interfaces:
IEnumerable<SomethingAppropriate>
IEnumerator<SomethingApropriate>
(thanks Jon and Marc for pointing out IEnumerator)
Example:
public IEnumerable<AClass> YourMethod()
{
foreach (XElement header in headersXml.Root.Elements())
{
yield return (ParseHeader(header));
}
}
yield is a lazy producer of data, only producing another item after the first has been retrieved, whereas returning a list will return everything in one go.
So there is a difference, and you need to declare the method correctly.
For more information, read Jon's answer here, which contains some very useful links.
It's a tricky topic. In a nutshell, it's an easy way of implementing IEnumerable and its friends. The compiler builds you a state machine, transforming parameters and local variables into instance variables in a new class. Complicated stuff.
I have a few resources on this:
Chapter 6 of C# in Depth (free download from that page)
Iterators, iterator blocks and data pipelines (article)
Iterator block implementation details (article)
"yield" creates an iterator block - a compiler generated class that can implement either IEnumerable[<T>] or IEnumerator[<T>]. Jon Skeet has a very good (and free) discussion of this in chapter 6 of C# in Depth.
But basically - to use "yield" your method must return an IEnumerable[<T>] or IEnumerator[<T>]. In this case:
public IEnumerable<AClass> SomeMethod() {
// ...
foreach (XElement header in headersXml.Root.Elements()){
yield return (ParseHeader(header));
}
}
List implements Ienumerable.
Here's an example that might shed some light on what you are trying to learn. I wrote this about 6 months
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace YieldReturnTest
{
public class PrimeFinder
{
private Boolean isPrime(int integer)
{
if (0 == integer)
return false;
if (3 > integer)
return true;
for (int i = 2; i < integer; i++)
{
if (0 == integer % i)
return false;
}
return true;
}
public IEnumerable<int> FindPrimes()
{
int i;
for (i = 1; i < 2147483647; i++)
{
if (isPrime(i))
{
yield return i;
}
}
}
}
class Program
{
static void Main(string[] args)
{
PrimeFinder primes = new PrimeFinder();
foreach (int i in primes.FindPrimes())
{
Console.WriteLine(i);
Console.ReadLine();
}
Console.ReadLine();
Console.ReadLine();
}
}
}
I highly recommend using Reflector to have a look at what yield actually does for you. You'll be able to see the full code of the class that the compiler generates for you when using yield, and I've found that people understand the concept much more quickly when they can see the low-level result (well, mid-level I guess).
To understand yield, you need to understand when to use IEnumerator and IEnumerable (because you have to use either of them). The following examples help you to understand the difference.
First, take a look at the following class, it implements two methods - one returning IEnumerator<int>, one returning IEnumerable<int>. I'll show you that there is a big difference in usage, although the code of the 2 methods is looking similar:
// 2 iterators, one as IEnumerator, one as IEnumerable
public class Iterator
{
public static IEnumerator<int> IterateOne(Func<int, bool> condition)
{
for(var i=1; condition(i); i++) { yield return i; }
}
public static IEnumerable<int> IterateAll(Func<int, bool> condition)
{
for(var i=1; condition(i); i++) { yield return i; }
}
}
Now, if you're using IterateOne you can do the following:
// 1. Using IEnumerator allows to get item by item
var i=Iterator.IterateOne(x => true); // iterate endless
// 1.a) get item by item
i.MoveNext(); Console.WriteLine(i.Current);
i.MoveNext(); Console.WriteLine(i.Current);
// 1.b) loop until 100
int j; while (i.MoveNext() && (j=i.Current)<=100) { Console.WriteLine(j); }
1.a) prints:
1
2
1.b) prints:
3
4
...
100
because it continues counting right after the 1.a) statements have been executed.
You can see that you can advance item by item using MoveNext().
In contrast, IterateAll allows you to use foreach and also LINQ statements for bigger comfort:
// 2. Using IEnumerable makes looping and LINQ easier
var k=Iterator.IterateAll(x => x<100); // limit iterator to 100
// 2.a) Use a foreach loop
foreach(var x in k){ Console.WriteLine(x); } // loop
// 2.b) LINQ: take 101..200 of endless iteration
var lst=Iterator.IterateAll(x=>true).Skip(100).Take(100).ToList(); // LINQ: take items
foreach(var x in lst){ Console.WriteLine(x); } // output list
2.a) prints:
1
2
...
99
2.b) prints:
101
102
...
200
Note: Since IEnumerator<T> and IEnumerable<T> are Generics, they can be used with any type. However, for simplicity I have used int in my examples for type T.
This means, you can use one of the return types IEnumerator<ProductMixHeader> or IEnumerable<ProductMixHeader> (the custom class you have mentioned in your question).
The type List<ProductMixHeader> does not implement any of these interfaces, which is the reason why you can't use it that way. But Example 2.b) is showing how you can create a list from it.
If you're creating a list by appending .ToList() then the implication is, that it will create a list of all elements in memory, while an IEnumerable allows lazy creation of its elements - in terms of performance, it means that elements are enumerated just in time - as late as possible, but as soon as you're using .ToList(), then all elements are created in memory. LINQ tries to optimize performance this way behind the scenes.
DotNetFiddle of all examples
#Ian P´s answer helped me a lot to understand yield and why it is used. One (major) use case for yield is in "foreach" loops after the "in" keyword not to return a fully completed list. Instead of returning a complete list at once, in each "foreach" loop only one item (the next item) is returned. So you will gain performance with yield in such cases.
I have rewritten #Ian P´s code for my better understanding to the following:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace YieldReturnTest
{
public class PrimeFinder
{
private Boolean isPrime(int integer)
{
if (0 == integer)
return false;
if (3 > integer)
return true;
for (int i = 2; i < integer; i++)
{
if (0 == integer % i)
return false;
}
return true;
}
public IEnumerable<int> FindPrimesWithYield()
{
int i;
for (i = 1; i < 2147483647; i++)
{
if (isPrime(i))
{
yield return i;
}
}
}
public IEnumerable<int> FindPrimesWithoutYield()
{
var primes = new List<int>();
int i;
for (i = 1; i < 2147483647; i++)
{
if (isPrime(i))
{
primes.Add(i);
}
}
return primes;
}
}
class Program
{
static void Main(string[] args)
{
PrimeFinder primes = new PrimeFinder();
Console.WriteLine("Finding primes until 7 with yield...very fast...");
foreach (int i in primes.FindPrimesWithYield()) // FindPrimesWithYield DOES NOT iterate over all integers at once, it returns item by item
{
if (i > 7)
{
break;
}
Console.WriteLine(i);
//Console.ReadLine();
}
Console.WriteLine("Finding primes until 7 without yield...be patient it will take lonkg time...");
foreach (int i in primes.FindPrimesWithoutYield()) // FindPrimesWithoutYield DOES iterate over all integers at once, it returns the complete list of primes at once
{
if (i > 7)
{
break;
}
Console.WriteLine(i);
//Console.ReadLine();
}
Console.ReadLine();
Console.ReadLine();
}
}
}
What does the method you're using this in look like? I don't think this can be used in just a loop by itself.
For example...
public IEnumerable<string> GetValues() {
foreach(string value in someArray) {
if (value.StartsWith("A")) { yield return value; }
}
}

Categories