Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions graph/patterns/enums.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,72 @@ Additionally speaking, depending on the situation, a nullable enum can very like

If used, `EnumType` names should be singular if the are non-flags enums, and the names should be plural if they are flags enums.


#### Nullable enums

Enum properties can be marked `Nullable="true"`, which means the property can hold `null` in addition to any defined member.
Before making an enum property nullable, consider whether a sentinel member like `none` better communicates the intent.

##### `null` vs `none`

| Value | Meaning | Use when |
|---|---|---|
| `null` | The property has no value — it was never set or is not applicable | The absence of a value is semantically different from every defined member |
| `none` | An explicit "nothing selected" choice within the enum's domain | "No selection" is a valid, intentional state the caller can set |

> **Note:** The `unknownFutureValue` sentinel is always required as the last known member of every enum (see [evolvable enums](./evolvable-enums.md)).
> It is unrelated to nullability and must be present regardless of whether the property is nullable or uses a `none` member.

##### Prefer a `none` member over nullable

In most cases, add a `none` member (value `0`) instead of making the property nullable.
This keeps the property non-nullable, which is simpler for SDK consumers and avoids the three-way ambiguity of "is it null, is it none, or is it a real value?"

```xml
<!-- ✅ RECOMMENDED — explicit 'none' member -->
<EnumType Name="priority">
<Member Name="none" Value="0"/>
<Member Name="low" Value="1"/>
<Member Name="normal" Value="2"/>
<Member Name="high" Value="3"/>
<Member Name="unknownFutureValue" Value="4"/>
</EnumType>

<Property Name="priority" Type="microsoft.graph.priority" Nullable="false"/>
```

##### When nullable is appropriate

Use `Nullable="true"` on an enum property only when **all** of the following apply:

1. **Absence is meaningful** — `null` represents "not set" or "not applicable," which is semantically distinct from every enum member including a hypothetical `none`.
2. **A sentinel member would be misleading** — adding `none` would imply the caller actively chose "nothing," but the actual semantics are that the property doesn't apply to this instance.
3. **The property is optional on creation** — the service does not assign a default value; `null` is the expected state until the caller explicitly sets one.

```xml
<!-- Acceptable — null means "not yet evaluated" which is distinct from any severity level -->
<Property Name="severity" Type="microsoft.graph.severity" Nullable="true"/>
```

##### Anti-pattern: nullable + `none`

Do **not** combine a nullable enum with a `none` member.
This creates two ways to express "no value" and forces callers to handle both `null` and `none`, leading to inconsistency and bugs.

```xml
<!-- ❌ WRONG — ambiguous: is "no value" null or none? -->
<EnumType Name="priority">
<Member Name="none" Value="0"/>
<Member Name="low" Value="1"/>
<Member Name="high" Value="2"/>
<Member Name="unknownFutureValue" Value="3"/>
</EnumType>

<Property Name="priority" Type="microsoft.graph.priority" Nullable="true"/>
```

Pick one: either `none` with `Nullable="false"`, or no `none` member with `Nullable="true"`.

#### Flag Enums or Collection of Enums

In case an enum can have multiple values at the same time the tentation is to model the property as a collection of Enums:
Expand Down