```
using System;
using System.Collections.Generic;
public static class Sieve
{
public static IEnumerable<int> Primes(int max)
{
if (max < 0)
throw new ArgumentOutOfRangeException(nameof(max));
var primeMultiples = new HashSet<int>();
for (var i = 2; i <= max; i++)
{
if (primeMultiples.Contains(i))
continue;
for (var j = i * 2; j <= max; j += i)
primeMultiples.Add(j);
yield return i;
}
}
}
```

The first step is to check the input for validity:

```
if (max < 0)
throw new ArgumentOutOfRangeException(nameof(max));
```

We then create a `HashSet<int>`

that will contain the numbers that are a multiple of the primes we find:

```
var primeMultiples = new HashSet<int>();
```

We then start iterating from `2`

(the smallest prime) up until the maximum that was specified:

```
for (var i = 2; i <= max; i++)
```

Within the loop, our first check is to see if the current number (`i`

) is a multiple of one of the primes we found.
If so, we'll skip the number as it can't be a prime:

```
if (primeMultiples.Contains(i))
continue;
```

If this check returns `false`

, we're dealing with a prime!
This means that we can then cross off any multiples of this prime, which we can do with another (nested) `for`

-loop:

```
for (var j = i * 2; j <= max; j += i)
primeMultiples.Add(j);
```

Note how we start at the first multiple of the prime (`i * 2`

) and that we increment the loop iterator variable by the prime number (`j += i`

) to iterate over all the multiples of the prime.

The final step is to return the prime number, for which we use a `yield`

statement:

```
yield return i;
```

Note that even though we yield an indidivual integer, what is returned from a caller's viewpoint is a sequence of integers.

When a `yield`

statement is written, the compiler transforms the method into a state machine that is suspended after each yield statement.

Methods that use a `yield`

statement are also *lazy*, which means that calling `Sequence(number)`

by itself does not do anything.
It is only when a method is called that forces evaluation (like `Count()`

or `ToArray()`

), that we're forcing iteration over the elements in the sequence.