# [Flags] — a value that holds several members

> [Flags] makes an enum's members bits, so one value can hold several of them at once — Access.Read | Access.Write. Combine members with | & ^ ~, test one with HasFlag, and a combined value reads as the members it holds ("Read, Write"), exactly as C# prints it. Every member needs an explicit power-of-two value.

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

## Summary        {#summary}

A `[Flags]` enum is a set of switches: each member is one bit, and a value holds any combination of them. Build a
combination with `|`, test for a member with `HasFlag`, and read a combination back as the members it holds.

```osy syntax
[Flags]
enum Access { None = 0, Read = 1, Write = 2, Delete = 4 }

Access rights = Access.Read | Access.Write;
rights.HasFlag(Access.Write)      // true
$"{rights}"                        // "Read, Write"
```

## Signature      {#signature}

```osy syntax
[Flags]
enum <Name> { None = 0, <A> = 1, <B> = 2, <C> = 4 }

bool <value>.HasFlag(<Name> flag)
<Name> a | b    <Name> a & b    <Name> a ^ b    <Name> ~a
```

## Description    {#description}

### Every member needs its value   {#values}

Each member of a `[Flags]` enum is a bit, so write its value: the powers of two, `1, 2, 4, 8, …`, and `0` for a
member meaning "none". An enum normally counts on from the previous member, which here would give `0, 1, 2, 3` — and
`3` is not a bit, it is `1 | 2`. So a member without a value is a compile error that names the fix.

A member may also name a combination on purpose — `ReadWrite = 3` — and a value that equals it reads as that name.

### Combining and testing   {#operators}

`|` adds members, `&` keeps only the members both sides hold, `^` toggles, and `~` inverts. The result of any of them
is still the enum, so it can be stored, passed and tested like a single member.

`HasFlag(flag)` is true when every bit of `flag` is set — the same as `(value & flag) == flag`. It works in a
function, in a component, and inside a query predicate:

```osy syntax
var editors = Share.Where(s => s.Rights.HasFlag(Access.Write)).Count();
```

### How a combination reads   {#words}

`.Name`, `.Label`, string interpolation and `+` all read a combination as the members it holds, smallest value
first, joined with `", "` — `"Read, Delete"`. When a member names the whole combination (`ReadWrite = 3`), that name
is used. Bits that no member names make the value print as its number (`9`), the way C# does rather than naming the
part it recognises. `.Description` joins the descriptions of the members that have one.

The server and the browser word a value identically: both are held to one shared table of cases, whose names are
checked against C#'s own output.

### A constant combination   {#const}

A combination of members is a compile-time constant, so a class can declare one:

```osy syntax
class Provider {
  public const Access Pushdown = Access.Read | Access.Write;
}
```

### What it cannot be combined with   {#refused}

| with | why it is refused |
|---|---|
| `[Type(string)]` | a stored member code names one member, and a flags value may hold several. A flags enum is stored as its number. |
| `[Role]` | a role is one member a person is granted; grant each role as its own row. |

## Examples       {#examples}

```osy test app=enum-flags-shares
// Who may do what with a shared folder — several rights at once.
[Flags]
enum Access { None = 0, Read = 1, Write = 2, Delete = 4 }

entity Share {
  [Required, MaxLength(200)] string Path;
  Access Rights;
  security { allow read, create, update when IsAuthenticated; }
}

void AllowWriting(Share s) {
  s.Rights = s.Rights | Access.Write;
}

int Writable() => Share.Where(s => s.Rights.HasFlag(Access.Write)).Count();
```

## See also       {#see-also}
- [enum](https://osysharp.com/reference/enum/declaration/) — declaring an enum and how it is stored
- [[Label], [Icon], [Tone] — what a human reads](https://osysharp.com/reference/enum/labels/) — `[Label]`, and what a screen shows for a member
