How it works...

Let's start by analyzing the main procedure. The first function we encounter is GetPrimes, which directly returns the enumerable (TPrimesEnumerable) over which you can iterate. The rest of the code is used to define the interface relative to the enumerable types, as seen in the previous recipe. 

The other interesting part of the code is related to the DoMoveNext function of the enumerator—the while True loop is executed until a prime number is found, each time incrementing FCurrent by 1.

What's the magic part? Glad you asked!

With a classic iteration approach, you should start with a set already defined, and scroll through the elements one by one. By an enumerable mechanism instead, it is possible to calculate on the fly the current value with considerable benefits.

It is not necessary to have a list (or, more generic, a container) already full of values available, so in the case of very large or even infinite sets, there would be a problem with memory management. In this case, only the value of the current iteration is kept in memory, and is only calculated each time.

The power of enumerable types lies in the fact that you can simply return the next value instead of all the values at once. It doesn't need to create a list at all. No list, no memory issues.