Skip to main content

ZeroAlloc.StateMachine

Source-generated, zero-allocation finite state machines for .NET.

Add [StateMachine] and [Transition<TState, TTrigger>] to a partial class or struct. The generator emits a TryFire(TTrigger) method as a switch expression over (TState, TTrigger) tuples — no dictionary, no delegate dispatch, no heap allocation on the transition path.


Quick Example​

[StateMachine(InitialState = nameof(State.Idle))]
[Transition<State, Trigger>(From = State.Idle, On = Trigger.Submit, To = State.Pending)]
[Transition<State, Trigger>(From = State.Pending, On = Trigger.Pay, To = State.Done)]
[Terminal<State>(State = State.Done)]
public partial class OrderMachine { }

var machine = new OrderMachine();
machine.TryFire(Trigger.Submit); // true — Idle → Pending
machine.Current; // Pending

Contents​

PageDescription
Getting StartedInstall and define your first machine
Attributes[StateMachine], [Transition], [Terminal] reference
Source GeneratorWhat the generator emits — input/output examples
TestingUnit-test state machines without mocking
AOT & TrimmingNative AOT compatibility
PerformanceBenchmark results and allocation profile

Core Concepts​

PageDescription
States and TriggersEnums as states and triggers, naming conventions
TransitionsDirected edges, TryFire, ordering, entry/exit contract
Concurrent ModeCAS loop, Volatile.Read, hook ordering, guard restrictions
Composite StatesHierarchical sub-FSMs, dispatch order, shallow history
Timeout TransitionsAfterMs edges, lazy timers, race-safe CAS, IDisposable
Concurrent PartsMultiple independent FSMs in one class via [StateMachineGroup]
PersistenceRestore(state) rebuilds a persisted state: validated, no hooks, timers armed
Diagram ExportDiagram = true emits a Mermaid stateDiagram-v2 const string

Guides​

PageDescription
GuardsBlock transitions at runtime with When = true
Entry and Exit ActionsReact to state crossings with partial void hooks
Terminal StatesIntentional sinks and the [Terminal] attribute
Circuit Breaker ExampleReal-world use: thread-safe circuit breaker

Diagnostics​

IDSeverityDescription
ZSM0001WarningUnreachable state
ZSM0002WarningUnintentional sink state
ZSM0003WarningSingle-use trigger (possible typo)
ZSM0004ErrorConcurrent mode on a struct
ZSM0005ErrorComposite state on a concurrent machine
ZSM0006ErrorSub-machine is not a [StateMachine]
ZSM0007ErrorSub-machine trigger type mismatch
ZSM0008ErrorComposite state value not in TState
ZSM0009ErrorDuplicate composite state
ZSM0010ErrorHistory state without composite
ZSM0011ErrorComposite state cannot also be terminal
ZSM0012ErrorTimeout transition requires concurrent mode
ZSM0013ErrorAfterMs must be positive
ZSM0014Error[StateMachine] and [StateMachineGroup] are mutually exclusive
ZSM0015ErrorDuplicate state machine part name
ZSM0016ErrorTransition Part mismatch
ZSM0017Error[StateMachineGroup] declared with no parts
ZSM0018ErrorComposite state inside a group
ZSM0019ErrorIncompatible user-supplied Dispose
ZSM0020WarningDiagram = true on a class with no transitions
ZSM0021ErrorUser constructor must call HookConstructor()
ZSM0022WarningWhen = true is ignored on a concurrent machine
ZSM0023WarningContaining type is not partial
ZSM0024ErrorFile-local state machine
ZSM0025ErrorName differs only in case from another state machine
ZSM0026WarningCopies of a timed record share its timers
ZSM0027InfoRestore not generated: no parameterless constructor
ZSM0028InfoRestore not generated: conflicting member