C#: IEnumerable and Yield, not as easy as you thought

The concept of IEnumerable is probably quite well known, when we want to browse all the elements in a list, we often use the foreach function as follows.

foreach(Student student in students) {}
Image for post
Image for post
Photo by Pankaj Patel on Unsplash

Recalling on IEnumerable

An IEnumerable array has the following properties:
A read-only array that can only be read, cannot add or remove elements.
Only browse in one direction, from beginning to end.
Consider the following scenario, if we want to read a list of students from the file, we usually write

public List<Student> ReadStudentsFromFile(string fileName){   string[] lines = File.ReadAllLines(fileName);    // Create an empty list
List<Student> result = new List<Student>();
foreach (var line in lines){ Student student = ParseTextToStudent(line);
result.Add(student); //Add student into list
}
return result; // Return list
}
var students = ReadStudentsFromFile("students.txt");foreach(var student in students) {};
// Change the return type to IEnumerable
public IEnumerable <Student> ReadStudentsFromFile (string fileName)
{
string [] lines = File.ReadAllLines (fileName);
foreach (var line in lines)
{
Student student = ParseTextToStudent (line);
yield return student; // YIELD NÈ
}
}

// Used the same
var students = ReadStudentsFromFile ("students.txt");
foreach (var student in students) {};

Differentiate between return and yield return

We all know the most basic thing when writing a method: The return keyword will end the method, return the result, without running any further statements:

public int GetNumber() { return 5; }Console.WriteLine(GetNumber());
public IEnumerable<int> GetNumber()
{
yield return 5;
yield return 10;
yield return 15;
}
foreach (int i in GetNumber()) Console.WriteLine(i); //5 10 15
  1. Browse to the next word, the program runs into command line 4, get 10 results, print to the screen.
  2. Similar to the last element, after printing, the program ends.
public List <Student> ReadStudentsFromFile (string fileName)
{
string [] lines = File.ReadAllLines (fileName);
List <Student> result = new List <Student> (); // Create an empty list

foreach (var line in lines)
{
Student student = ParseTextToStudent (line);
result.Add (student); // Add student to the list
}
return result; // Return the list
}

public IEnumerable <Student> YieldReadStudentsFromFile (string fileName)
{
string [] lines = File.ReadAllLines (fileName);
foreach (var line in lines)
{
Student student = ParseTextToStudent (line);
yield return student;
}
}
  • In the second method, the result is immediately after the parse is the first student, with each subsequent loop, the program will continue running into the YieldReadStudentsFromFile method, taking the result out gradually.
  • As in the above case, suppose we have 50 lines, the ParseTextToStudent function takes 1s 1 time. In the old way, when calling the
  • ReadStudentsFromFile function, we had to wait for 50 seconds. With the YieldReadStudentsFromFile function, the ParseTextToStudent function is only run whenever we read the student’s information, which greatly increases performance (If we only take the first 5 students just wait for 5s).
  • In some cases, the list returns infinite elements or taking entire elements very time-consuming, we must use yield to solve.

Written by

Always be nice to anybody who has access to my toothbrush.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store