Switch expressions and is patterns
A JS switch is a statement: it falls through, needs break, and produces nothing. A C# switch expression is an expression: it evaluates to a value, has no fall-through, and each arm is pattern => result. You’ll use it to turn a value into another value, and it reads top to bottom like a lookup table.
// This is the shape Fusion endpoints use: match on the ERROR TYPE, not a string.
IResult response = result.Errors[0] switch
{
EntityNotFound e => Results.NotFound(e.Message),
DecisionNotFound e => Results.NotFound(e.Message),
DecisionAlreadyExists e => Results.Conflict(e.Message),
_ => Results.BadRequest(result.Errors),
};Notice you’re matching on the type of the error (EntityNotFound e), binding it to e in one move. That’s the is pattern: x is EntityNotFound e both tests the type and gives you a typed variable, replacing the TS if (x instanceof EntityNotFound) plus a cast.
The _ arm is the discard: the catch-all. In a mapping like the HTTP one above, a sensible default is fine. But when you’re switching over a closed set of domain values, a discard that silently returns a default is dangerous, because adding a new member later maps it to the wrong thing with no warning. Fusion anti-pattern #8 is explicit: in that case, the discard should throw.
// Wrong: a new enum member silently becomes 0.
var factor = reason switch { Weather => 1.0m, Mechanical => 0.5m, _ => 0m };
// Right: reaching the discard is genuinely unexpected, so shout.
var factor = reason switch
{
Weather => 1.0m,
Mechanical => 0.5m,
_ => throw new ArgumentOutOfRangeException(nameof(reason), reason, null),
};Try it yourself
Read a real result-to-HTTP switch
See the type-matching switch that every Fusion endpoint leans on.
- Open
presentation/api/DisruptionDecisions/DisruptionDecisionEndpoints.cs - Find where a failed
Resultis mapped to an HTTP response - Confirm it branches on the error TYPE (
EntityNotFound,DecisionNotFound), never on a status string like== "reverted" - Note this is convention E2 / anti-pattern #26 in action: endpoints branch on the Result, not domain status values
The discard arm
You write a switch expression over a SmartEnum of disruption reasons and add a _ => arm that returns 0m. What's the Fusion objection?
Show answer
Correct answer: A — A new reason added later silently maps to 0; the discard should throw instead
Anti-pattern #8: on a closed domain set, a value-returning discard hides the addition of a new member. Make it _ => throw new ArgumentOutOfRangeException(...) so an unhandled case fails loudly.