# Enumerable.Range

> A sequence of consecutive integers, count of them, starting at start. It is how you iterate by index — including in a render block, which has foreach and no for.

<!-- id: function-enumerable-range · area: function · stability: stable · html: https://osysharp.com/reference/function/enumerable-range/ -->

## Summary        {#summary}
`Enumerable.Range(start, count)` is a sequence of `count` consecutive integers beginning at `start`. It is what you
`foreach` over when the thing you are iterating is an index rather than a row — and it is the only way to do that
inside a **`render` block**, which has `foreach` and no `for`.

## Signature      {#signature}
```osy syntax
Enumerable.Range(<start>, <count>)   // → int[]  — count integers, starting at start
```

## Description    {#description}

### The second argument is a COUNT, not an end   {#count-not-end}
`Enumerable.Range(0, 4)` is `0, 1, 2, 3` — four values. This is C#'s signature exactly, and the mistake worth naming
once: it is not `Range(first, last)`.

- `count` of `0` is an empty sequence, and iterating it renders nothing. That is the case a count computed from data
  hits first, so it is well-defined rather than an error.
- A negative `count`, or a range whose last value would pass `int.MaxValue`, fails loudly.

### A fixed grid in a render block   {#in-render}
A `render` block iterates with `foreach`; there is no `for`. So anything laid out by position — a board, a calendar
month, a star rating, a fixed number of skeleton placeholders — is a `foreach` over a range:

```osy title="an 8x8 board" test app=function-range
[Page("/board")]
[AllowAnonymous]
component Board() {
  render {
    Stack(gap: 0) {
      foreach (var row in Enumerable.Range(0, 8)) {
        Row(gap: 0) {
          foreach (var col in Enumerable.Range(0, 8)) {
            Box(w: "40px", h: "40px", bg: (row + col) % 2 == 0 ? "#eee" : "#333");
          }
        }
      }
    }
  }
}
```

The inner range is evaluated per outer element, exactly as a nested loop reads.

### A range or a `for` loop, in a function body?   {#in-a-body}
It works in a function too, and there it is a matter of taste against [for](https://osysharp.com/reference/function/for-loop/): reach for `for` when you
need the index to *drive* something (a mutable step, an early exit), and for a range when you are iterating a fixed
number of values.

```osy title="a range in a body" test app=function-range
int SumTo(int n) {
  int total = 0;
  foreach (var i in Enumerable.Range(1, n)) { total = total + i; }
  return total;
}
```

### Is it lazy? — no, it MATERIALISES   {#materialises}
C#'s `Enumerable.Range` is lazy; this one produces the whole sequence. So it is for a grid, not for a per-pixel loop:
a few hundred or a few thousand values is ordinary, and a range of hundreds of thousands allocates all of them. The
sequence is a real list — `foreach` it, take its `.Count`, or run the LINQ surface over it.

## Examples       {#examples}
```osy title="counting, and the empty case" test app=function-range
int Count() { return Enumerable.Range(0, 5).Count; }          // 5
int Empty() { return Enumerable.Range(0, 0).Count; }           // 0 — well-defined, not an error
int Offset() { return Enumerable.Range(3, 4).Count; }          // 3, 4, 5, 6
int EvensTo(int n) { return Enumerable.Range(0, n).Where(i => i % 2 == 0).Count; }
```

## See also       {#see-also}
- [foreach](https://osysharp.com/reference/function/foreach/) — the loop this feeds
- [for](https://osysharp.com/reference/function/for-loop/) — the indexed loop a function body can use instead (a render block cannot)
- [[ui-component#render-tree]] — what a render block may contain
- [Array literals](https://osysharp.com/reference/function/collection-literals/) — a sequence written out (`[1, 2, 3]`) rather than generated
