# Enums

> A fixed set of named values, used as a member type. By default an enum stores as a compact number; add [Type(string)] to store the member's own name instead — what you want when a human or another system reads the column. [Label] gives a member the human-readable label a screen shows. Three answers you will want before you open a page. (1) Room.Members is every member, in declaration order — `foreach (var r in Room.Members)` is how you build a picker, a tab bar or a filter; never hardcode the list, and Enum.GetValues<Room>() is the same array if you prefer C#'s spelling. (2) A member may be named for its own type: `[Required] Room Room;` compiles, exactly as `Color Color` does in C#. (3) Text(p.Room) renders the [Label] label, but "in " + p.Room concatenates the raw member NAME ("LivingRoom") — say p.Room.Label wherever a string is what you need. Full detail: osy docs enum-declaration#members and osy docs enum-labels#label-property.

<!-- id: enum-index · area: enum · stability: stable · html: https://osysharp.com/reference/enum/index/ -->

## Summary        {#summary}
An `enum` is a **fixed set of named values** — `enum Status { Draft, Placed, Cancelled }` — used as the type of a
member. It gives you a closed vocabulary the compiler checks: a value outside the set is a compile error, not a bad
row. Two small decisions round it out: **how it is stored** (a number, or its name) and **what a human sees** (its
label).

## Description    {#description}

### Declaring one   {#declaring}
An [enum](https://osysharp.com/reference/enum/declaration/) lists its members; any member or property can then take the enum as its type (an
`entity Order { Status Status; }`, a function local, a component prop). The compiler enforces the set everywhere the
enum is used, so a typo or a stale value is caught at compile time:

```osy title="a closed set the compiler checks" test app=enum-index
enum Status { Draft, Placed, Cancelled }
```

```osy title="proof: the members are distinct values" run app=enum-index
[Test]
void Status_is_a_fixed_set() {
  var s = Status.Placed;
  Assert.NotEqual(Status.Draft, s);
}
```

### Stored as a number, or as its name   {#storage}
By default an enum member is stored as a **number** — compact, and fine when only your own code reads it. When a
human or another system will read the column, store it as the member's **own name** with `[Type(string)]`, so the
value in the database is `"Placed"` rather than `1`. That is the setting to reach for on anything exported, reported
on, or read by an integration. See [enum](https://osysharp.com/reference/enum/declaration/).

### The label a human reads   {#labels}
A member's stored value is compact; the label on screen doesn't have to be. [[Label], [Icon], [Tone] — what a human reads](https://osysharp.com/reference/enum/labels/) — `[Label("…")]` — gives
a member a human-readable label (the member's own name is the default), and a doc comment gives it a longer
description. So `InProgress` can show as "In progress" without changing what is stored.

## See also       {#see-also}
- [enum](https://osysharp.com/reference/enum/declaration/) — declaring the set, and `[Type(string)]` for name storage
- [[Label], [Icon], [Tone] — what a human reads](https://osysharp.com/reference/enum/labels/) — `[Label]` and the human-facing label
- [Types](https://osysharp.com/reference/types/index/) — the rest of the type system
