I have a simple function that I'm just using as an example here. It's an infinite enumeration!
public static IEnumerable<int> Roll()
{
while (true)
{
yield return new Random().Next(1, 6);
}
}
And I want this function to keep rolling for a specific amount of clock ticks so I have this method:
public static List<T> Ticks<T>(this IEnumerable<T> data, int time)
{
var list = new List<T>();
Stopwatch timer = null;
foreach (var item in data)
{
if (timer == null)
{
timer = Stopwatch.StartNew();
}
if (timer.ElapsedTicks < time)
{
list.Add(item);
}
else
{
break;
}
}
timer?.Stop();
return list;
}
But I don't really like how I had to write that as I rather have something more like this:
public static List<T> Ticks2<T>(this IEnumerable<T> data, int time)
{
var list = new List<T>();
Stopwatch timer = Stopwatch.StartNew();
using (var en = data.GetEnumerator())
{
while (timer.ElapsedTicks < time && en.MoveNext())
{
list.Add(en.Current);
}
}
timer.Stop();
return list;
}
But the latter function will fail as the GetEnumerator() method will aggregate all data and in an infinitive enumeration, that takes forever...
Wait... I'm wrong... It turned out to be so fast that my list ran out of memory... It's not aggregating, fortunately...
The Ticks() method works fine, btw! I can use this:
Console.WriteLine( Watch.Roll().Ticks(10000).AllToString().AllJoin(", ") );
And it will roll until 10,000 ticks have passed, convert everything to strings and join everything while keeping the chain of methods. This is important, btw. I cannot accept any answer that will break the method chain. Keep in mind that this is just an example.
And no, I can't change anything to that Roll() method. That method is read-only...
So, how can I rewrite this Ticks() method more similar to the Ticks2() method without ending up aggregating all data?
For those curious to the AllToString() and AllJoin methods:
public static IEnumerable<string> AllToString<T>(this IEnumerable<T> data) => data.Select(item => item.ToString());
public static string AllJoin<T>(this IEnumerable<T> data, string separator) => string.Join(separator, data.AllToString());
These two methods can be practical for other solutions where you'd be using enumerations and want string output.