C
C#16mo ago
Becquerel

✅ Interesting uses of yield return

I recently needed to generate an arbitrary number of unique random numbers, and after a little thinking I found I could get a really elegant solution by using yield return to generate an infinite stream of ints. This made me realise I basically never use this language feature and there's probably a lot of cool applications for it I'm missing. Any tricks/interesting patterns you've written with it?
16 Replies
Becquerel
Becquerel16mo ago
for anyone interested, what I did was this:
private IEnumerable<int> GetRandom(int max)
{
while (true)
{
yield return Random.Shared.Next(max);
}
}

var randoms = GetRandom(someNumber)
.Distinct()
.Take(amount)
.ToList();
private IEnumerable<int> GetRandom(int max)
{
while (true)
{
yield return Random.Shared.Next(max);
}
}

var randoms = GetRandom(someNumber)
.Distinct()
.Take(amount)
.ToList();
ero
ero16mo ago
(basically just)
Enumerable.Range(0, amount)
.Select(_ => Random.Shared.Next(someNumber))
.Distinct()
.ToList();
Enumerable.Range(0, amount)
.Select(_ => Random.Shared.Next(someNumber))
.Distinct()
.ToList();
Kesa
Kesa16mo ago
yield return is indeed very useful
ero
ero16mo ago
I'd say it's rarely used in the way they're using it here
Becquerel
Becquerel16mo ago
damn, I should have thought of that!
Thinker
Thinker16mo ago
What they're most useful for is probably returning collections of things where each item is potentially computationally intensive and where it's useful to let the caller decide how many items it needs. It's like a task in the sense that the caller can decide to interrupt the enumeration (and therefore execution of the method) at any time. (hell, Unity uses yield for its async stuff)
Anton
Anton16mo ago
this can give you fewer numbers than amount I suppose there's no built-in infinite range in linq
Cattywampus
Cattywampus16mo ago
it's not true async btw coffeevee
ero
ero16mo ago
Yeah I noticed as soon as I posted. Would this be a worthwhile proposal?
Anton
Anton16mo ago
what do you mean?
ero
ero16mo ago
Propose an infinite range in Linq to dotnet/runtime
Anton
Anton16mo ago
I guess it's no different than introducing ISystemClock or similar helpers that you can code in 3 lines
canton7
canton716mo ago
Why do you need an infinite range thing? If you keep asking OP's GetRandom for the next value, it will keep giving you one -- an infinite stream of random values. No need to generate an infinite range and then map each element to a random value, or something
Becquerel
Becquerel16mo ago
i will note one little discrepancy in my original code i'm curious about if the amount you .Take() is greater than max, the program will deadlock eventually i figured out this was because it's obviously impossible to have, say, 50 unique numbers less than 34 but i was surprised i didn't get an exception anywhere i don't know if there's an intelligent way to order the LINQ methods so that kind of subtle bug is more obvious think
canton7
canton716mo ago
Hmm, I don't think so. The knowledge required to detect that problem is kinda spread out over the whole pipeline.
Becquerel
Becquerel16mo ago
RIP