Summary#
Enum.Parse<T>(text) answers the member of T that text names — Enum.Parse<OrderState>("Paid") is
OrderState.Paid. A name the enum does not have throws an ArgumentException naming the enum and listing every
member. Enum.TryParse<T>(text, out var v) is the same parse without the throw: it answers false and leaves you to
say what an unknown name means.
OrderState s = Enum.Parse<OrderState>("Paid"); // OrderState.Paid
OrderState t = Enum.Parse<OrderState>("paid", ignoreCase: true);
if (Enum.TryParse<OrderState>(text, out var state)) { … } // false for "Shiped"Signature#
T Enum.Parse<T>(string value)
T Enum.Parse<T>(string value, bool ignoreCase)
bool Enum.TryParse<T>(string value, out T result)
bool Enum.TryParse<T>(string value, bool ignoreCase, out T result)
bool Enum.TryParse(string value, out T result) // T named on the `out`Description#
What text does it accept?#
The rules are C#'s:
| text | Enum.Parse<OrderState>(…) |
|---|---|
"Paid" | OrderState.Paid — a member name, compared exactly |
" Paid " | OrderState.Paid — surrounding whitespace is trimmed |
"paid" | throws; with ignoreCase: true, OrderState.Paid |
"1" | the member whose value is 1 — text that is a number parses as a value |
"Read, Write" | on a [Flags] enum, the members combined — the way the value prints ([Flags] — a value that holds several members) |
"Shiped", "" | throws ArgumentException: Requested value 'Shiped' was not found in OrderState — it has: Placed, Paid, Shipped, Cancelled. |
null | throws ArgumentNullException |
How is it different from C#?#
In one place, on purpose. C# also accepts a number no member has: Enum.Parse<OrderState>("99") is
(OrderState)99 there. Osy# refuses it like any other unknown value. An enum value is stored as its member's key,
and 99 would be stored as a key that no member names and no label can show. On a [Flags] enum, a number made of
declared bits ("7" for Read | Write | Delete) is accepted, because the enum can hold that value.
A [Type(string)] enum stores the member's name, so it parses names only, never numbers or a comma list.
When should I use TryParse instead?#
Use Parse when the text should already be valid and a bad value is a bug, such as a value your own code wrote.
Use TryParse for text from a person or another system, where an unknown name is something to report:
if (!Enum.TryParse<OrderState>(input, out var state)) {
throw new ArgumentException($"'{input}' is not an order state.");
}
order.State = state;Declare the variable in the call (out var state, or out OrderState state). Filling a variable that already
exists is refused: on failure C# writes default(T) into it, which is the value 0, and the enum may not declare 0.
⚠ Do not write your own switch over names that falls back to a member. A typo then becomes that member without
any error, for example an order that is silently cancelled. osy lint reports that shape as
correctness-enum-name-with-a-silent-default. A fallback member named for not knowing (Unknown, Other, None) is
an honest answer and is not reported. When the text names the next state of a row, take the enum instead of a string,
or write one function per move (An entity's lifecycle — a workflow that tracks its status, or one function per move).
Where does it run?#
Everywhere an expression runs: a function on the server, and an action or render block in the browser, with no round trip. The members are known when the app compiles, so both sides give the same answer, with the same message.
Examples#
enum OrderState { Placed, Paid, [Label("On its way")] Shipped, Cancelled }
entity Order {
[Required, MaxLength(40)] string Ref;
OrderState State;
security { allow read, create, update when IsAuthenticated; }
}
// Text from an import or a form: an unknown state is reported, never guessed.
string SetState(Order order, string text) {
if (!Enum.TryParse<OrderState>(text, true, out var state)) {
return $"'{text}' is not an order state.";
}
order.State = state;
return $"Now {state.Label}.";
}
// Text the app wrote itself: a bad value is a bug, so let it throw.
OrderState Stored(string name) => Enum.Parse<OrderState>(name);[Test]
void Parsing_names_a_member_or_refuses() {
Assert.Equal(OrderState.Shipped, Stored("Shipped"));
Assert.Equal(OrderState.Paid, Enum.Parse<OrderState>("paid", true));
Assert.False(Enum.TryParse<OrderState>("Shiped", out var typo));
Assert.Throws<ArgumentException>(() => Stored("Shiped"));
}See also#
- enum — declaring an enum and how its members are stored
- [Label], [Icon], [Tone] — what a human reads —
.Labeland.Name, the way back from a member to text - [Flags] — a value that holds several members —
[Flags]values, which parse from"Read, Write"