Osy#the first language built for agents
Agents firstAgentic appsWorkflowsDurable Execution — built inSecurityTestingThe editorThe UI modelOne program

Reference / Function

foreach

foreach (var <item> in <collection>) { … }

Walks a collection — a query result, a list, or a parent's children. The normal way to iterate; reach for a for loop only when you need the index.

stable3 examples compiled by CIfunctioncontrol-flow

Summary#

foreach walks a collection, binding each element to a local. It is the normal loop: a materialised query result, a List<T>, or a parent's children all iterate the same way.

Signature#

foreach (var <item> in <collection>) { … }

Description#

Walking a query result#

Materialise the query with .ToList(), then walk it:

entity Order {
  [Required] string Code;
  decimal Total;
}

decimal TotalOver(decimal threshold) {
  var sum = 0m;
  foreach (var o in Order.Where(x => x.Total > threshold).ToList()) {
    sum += o.Total;
  }
  return sum;
}

Note the accumulator is seeded 0m, not 0 — see var.

Walking a parent's children#

A parent's collection member iterates directly. This is the connected path through the object graph, and the reason you should never fetch children with a separate filtered query (relations):

entity Invoice {
  [Required] string Number;
  [ForeignKey(Invoice)] InvoiceLine[] Lines;
}

entity InvoiceLine {
  [Required] Invoice Invoice;
  decimal Amount;
}

decimal InvoiceTotal(string number) {
  var inv = Invoice.Single(i => i.Number == number);
  var total = 0m;
  foreach (var line in inv.Lines) {
    total += line.Amount;
  }
  return total;
}

Walking a list#

string Join(string csv) {
  var joined = "";
  foreach (var part in Text.Split(csv, ",")) {
    joined += Text.Trim(part);
  }
  return joined;
}

Walking the characters of a string#

A string is a sequence of one-character strings, so foreach walks it exactly as it walks a list — there is no separate character type to learn, and ch is an ordinary string you can compare, append and pass on:

```osy title="a character at a time, and what ch is" syntax int Commas(string line) { var n = 0; foreach (var ch in line) { if (ch == ",") { n = n + 1; } } return n; }


The loop lowers to `Text.Chars(line)`, which you may also call directly when you want the characters as a
`string[]` rather than a loop — `Text.Chars("abc")` is `["a", "b", "c"]`.

### When you need the index   {#index}
`foreach` gives you the element, not its position. When the position is what you are after, use a
[`for`](/reference/function/for-loop/) loop.

### How do I stop part-way through?   {#leaving}
`break` and `continue` work as they do in C# — see [break / continue](/reference/function/break-continue/).

## See also       {#see-also}
- [for](/reference/function/for-loop/) — when you need the index
- [break / continue](/reference/function/break-continue/) — leaving a loop, or skipping an element
- [relations](/reference/entity/relations/) — why children are walked through the collection
- [Where / Single / Count](/reference/query/where/) — producing the result you walk

Related

for

The C-style counting loop. Runs init once, then repeats the body while cond holds, running update after each pass. Any…

break / continue

break leaves the enclosing loop; continue skips the rest of this pass. Inside a switch, break leaves the SWITCH, not…

relations

One entity points at another by declaring it as a member — that is the foreign key. The parent reads its children back…

Where / Single / Count

Query an entity by writing a predicate over it. The query runs in the database — not a filter over rows you already…