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