Home » News » Improving Performance using Yield on C#

Improving Performance using Yield on C#

Hi guys,

This is a tip for you who want better performance when executing your programs, and also wants a clean and simple syntax.
Let’s understand a little more about Yield definition before we show how to use it.
The key word yield indicates to the compiler that the method in which it appears is an iterator.

The compiler generates a class to implement the behavior that is expressed in the iterator block.
In iterate block, the yield keyword is used along with the return keyword to provide a value to the enumerator object. This is the value returned, for example, in each of a foreach loop-statement. The yield keyword is also used to break to signal the end of the iteration.

To know more about iterators,  check this link Iterators (C# Programming Guide).

Example of use::

yield return <expression>;
yield break;

In a yield return statement, the expression is evaluated and returned as a value to the enumerator object; the expression must be implicitly convertible to the type of iterator yield.
In a yield break statement, control is returned unconditionally to the iterator “caller”, which is the method IEnumerator.MoveNext (or its generic System.Collections.Generic.IEnumerable (Of T) counterpart) or the Dispose method of the enumerator object.
The yield statement can only appear within an iterator block, which can be implemented as the body of the method, operator or accessor. The body of such methods, operators or accessors is controlled by the following restrictions:

  • Unsafe blocks are not allowed.
  • Parameters for the method, operator or accessor can not be ref or out.
  • A yield return statement can not be used anywhere within a try-catch block.
  • Can be used in a try block if the try block is followed by a finally block.
  • A yield break statement can be used in a catch or a try block, but not in a finally block.
  • The yield statement can not appear in an anonymous method. For more information, see Anonymous Methods (C # Programming Guide).

For more information about the yield visit the MSDN.

Right, so far we have done our homework and consequently we learned the theory.

The good theories are the ones that we put into practice and make sense. So now let’s try it.

Let’s create a method to return a list of integers, pay attention in the process we instantiate a list and we add our value to this list and at the end we return this list.

public static IEnumerable<long> GetList()
{
   var list = new List<long>();
   for (long i = 0; i < 10000000; i++)
      list.Add(i);
   
   return list;
}

Now let’s use the C# yield, note that it is not necessary to instantiate the list and the syntax is much simpler.

public static IEnumerable<long> GetListYield()
{
   for (long i = 0; i < 10000000; i++)
      yield return i;
}

So far visually speaking the methods are the same and do the same thing. But which one is best?
What would you do to check? Instantiate a variable time and count the time before and after execution of the methods?
It’s a good test, but if the execution is so fast that we are not able to see the difference?
In this case we will use the System.Diagnostics to help us, specifically will use the Stopwatch class.

public void Execute()
{
   var stopwatch = new System.Diagnostics.Stopwatch();
   stopwatch.Start();
   var list1 = GetList();
   stopwatch.Stop();
   var elapsedTicks1 = stopwatch.ElapsedTicks;
   stopwatch.Restart();
   var list2 = GetListYield();
   stopwatch.Stop();
   var elapsedTicks2 = stopwatch.ElapsedTicks;
}

OK! Do your debug test on your machine and check how fast is the method that uses the Yield syntax.

Just to illustrate this post I got the elapsedTicks1 equals 437,031 and elapsedTicks2 eaquals 1158.

 

Thanks for reading.
Like and Share if you found it may be useful to someone you know!

Would you like to check the Portuguese version?
Click on the Brazilian flag -> Brazil

Deixe um comentário