C
C#Esa

yield???

public IEnumerable<int> A()
{
for (int i = 0; i <= 10; i += 2)
yield return i;
}



public IEnumerable<int> B()
{
var ints = new List<int>();
for (int i = 0; i <= 10; i += 2)
ints.Add(i);

return ints;
}
public IEnumerable<int> A()
{
for (int i = 0; i <= 10; i += 2)
yield return i;
}



public IEnumerable<int> B()
{
var ints = new List<int>();
for (int i = 0; i <= 10; i += 2)
ints.Add(i);

return ints;
}
What is the difference here?
E
Esa394d ago
Is this only about the performance gain of not having to declare a new List, or is there something else im missing?
T
Thinker394d ago
The yield version doesn't actually allocate a list, it only yields its items when the caller actually requests it. The list has to allocate itself and a backing array. If you're actually concerned about performance here, benchmark it.
E
Esa394d ago
I'm just thinking pragmatically from a beginners point of view, as in "is this knowledge that's useful, or academic fluff"
T
Thinker394d ago
yield is definitely useful for instance, it can be used to construct infinite sequences
E
Esa394d ago
The usecase is flying well above my head sadly. Can you give some real world examples?
T
Thinker394d ago
sure, one sec For a simple example, this code generates an infinite sequence of factorial numbers.
static IEnumerable<BigInteger> Factorials()
{
BigInteger x = 1;
BigInteger i = 1;

while (true)
{
yield return x;

i++;
x *= i;
}
}
static IEnumerable<BigInteger> Factorials()
{
BigInteger x = 1;
BigInteger i = 1;

while (true)
{
yield return x;

i++;
x *= i;
}
}
This would be rather impractical to do with lists, if you just want a sequence of numbers You can do almost everything can do with yield with lists, but the benefit is that yield is lazy and only evaluates when the caller wants it. In the example above, the 10! isn't computed unless the caller actually wants that. (and yes the example above isn't actually very practical unless you really want a sequence of factorial numbers for whatever reason)
E
Esa394d ago
benchmark gone wrong lmao
T
Thinker394d ago
Another example would be if you have a tree structure
record Node<T>(T Value, Node<T>? Child);

static IEnumerable<Node<T>> GetDescendantNodes<T>(this Node<T> node)
{
var current = node;
while (current.Child is not null)
{
yield current.Child;
current = current.Child;
}
}
record Node<T>(T Value, Node<T>? Child);

static IEnumerable<Node<T>> GetDescendantNodes<T>(this Node<T> node)
{
var current = node;
while (current.Child is not null)
{
yield current.Child;
current = current.Child;
}
}
This descends through a node's descendants, but only to the depth the caller wants. The tree might be recursive, having a node which links back to a previous node, which would for a list be impossible to handle, but for an enumerable using yield is perfectly fine. Again the benefit is not having to compute the entire sequence unless it's actually needed. Also here's some benchmarks
| Method | Mean | Error | StdDev | Median | Gen0 | Allocated |
|------- |---------:|---------:|---------:|---------:|--------:|----------:|
| List | 26.37 us | 1.275 us | 3.660 us | 25.27 us | 83.3130 | 131400 B |
| Yield | 13.08 us | 0.068 us | 0.053 us | 13.07 us | 0.0153 | 32 B |
| Method | Mean | Error | StdDev | Median | Gen0 | Allocated |
|------- |---------:|---------:|---------:|---------:|--------:|----------:|
| List | 26.37 us | 1.275 us | 3.660 us | 25.27 us | 83.3130 | 131400 B |
| Yield | 13.08 us | 0.068 us | 0.053 us | 13.07 us | 0.0153 | 32 B |
[MemoryDiagnoser]
public class Benchmarks
{
[Benchmark]
public void List()
{
static List<int> List()
{
List<int> list = new();
for (int i = 0; i < 10_000; i++)
list.Add(i);
return list;
}

var list = List();

_ = list[5000];
}

[Benchmark]
public void Yield()
{
static IEnumerable<int> Enumerable()
{
for (int i = 0; i < 10_000; i++)
yield return i;
}

var enumerable = Enumerable();

_ = enumerable.ElementAt(5000);
}
}
[MemoryDiagnoser]
public class Benchmarks
{
[Benchmark]
public void List()
{
static List<int> List()
{
List<int> list = new();
for (int i = 0; i < 10_000; i++)
list.Add(i);
return list;
}

var list = List();

_ = list[5000];
}

[Benchmark]
public void Yield()
{
static IEnumerable<int> Enumerable()
{
for (int i = 0; i < 10_000; i++)
yield return i;
}

var enumerable = Enumerable();

_ = enumerable.ElementAt(5000);
}
}
So you can see that the list allocates significantly more memory, because it has to allocate the entire list, while the enumerable only has to compute as much as it actually needs. However the list is significantly faster (O(1)) in terms of access, while the enumerable is linear (O(n)).
E
Esa394d ago
Yup I actually did some tests. Thoroughly shocked at how big the difference was!
P
Pobiega394d ago
If you allocate the list to fit 10K items from the start, you'll get a lot better memory numbers.. but it will still be much higher than the yield 🙂
Want results from more Discord servers?
Add your server
More Posts
C# Data Table issuehttps://pastebin.com/DSHwSh0M based on this program, I need to set the values of the `Old PS A11Y S❔ Microsoft Graph SDK - Serializing objectsHello, I am currently working with Microsoft Graph API to work with the Planner. My goal is to backu❔ XML deserialise different types into a single listI'm using the build in XML serialisation library (unless it's with .NET framework?), and I current h❔ Access things from different scene in UnityI have a Class Selector scene that has a Class Selector Script component (MonoBehaviour) attached to❔ C# how do I write an If-statement to handle a button?Hi, I wanted some assistance with writing a If-statement that filters out the zones section in my ap❔ Magnetic Links for application?Hey, does someone have an article/tutorial/explanation how I can develop magnetic links for my appli❔ Show values from a list in a datagridview getting source from bindingsourceHello! I have the following problem: I am currently developing a winforms app with a datagridview th❔ Render email content .NET 7 (razor)I have to reinplement email content rendering, because currently its not looking really good, especi❔ GetAxis wont workpublic class Driver : MonoBehaviour { // Start is called before the first frame update const✅ (SOLVED)Help a Beginneri am following CodeMonkeys 11Hr youtube video on coding a game in unity. I have ran into a issue whe❔ Exclude items from linq query if they contain one from an array of substringsI've got a list of strings, that if they appear anywhere in a linq query column i want to exclude th✅ Comprehension questions (LeetCode Binary Search)Like the title says it's about this puzzle https://leetcode.com/problems/binary-search/description/ ❔ How to create a cubic function calculator that also calculates the minimum and maximum value```c Console.WriteLine("Please enter a, b, c, d for the cubic function ax^3+bx^2+cx+d"); ❔ how to listen to the output of a virtual audio device on windows using C#?how to listen to the output of a virtual audio device on windows using C# to save the raw audio stre❔ How to wait for process to completei want to make program opens async but instead of giving 'hard coded' delays but i don't know how to❔ Problem with including C DLL in a C# console app project.So I have this C DLL imported into my console app (.NET 5). I simply cannot get to call it correctly✅ Win Form Event Handlers questionHi, I was just wondering if there is an event handler when the win form is idle that I can then run ❔ Problem with Dictionary<ulong, Image> (Strange work of memory access)Concept of my system: A system that draws a picture with stickers, each of the stickers can be moved❔ How do I refactor this?I am working with a grid of tiles, each tile has an int, which is made up of 4 bytes which represent❔ [AvaloniaUI] Visibility of item in ListView based on conditionAn Avalonia UI application is used to manage an evidence of items. It allows the user to add items.