Arities: 2, 3, 4, 5, 6, 7, 8
// OneOf<T1, T2> — binary outcome
OneOf<Error, User> result = TryGetUser(id);
// OneOf<T1, T2, T3> — three-way outcome
OneOf<ValidationError, NotFoundError, User> result = ValidateAndGet(id);
// OneOf<T1, T2, T3, T4> — four-way outcome (v1.12.0+)
OneOf<ValidationError, UnauthorizedError, NotFoundError, Order> result = GetOrder(id);
// OneOf<T1, T2, T3, T4, T5> — five-way outcome (v1.27.0+)
OneOf<ValidationError, UnauthorizedError, NotFoundError, ConflictError, Order> result = ProcessOrder(id);
// OneOf<T1, T2, T3, T4, T5, T6> — six-way outcome (v1.27.0+)
OneOf<ValidationError, UnauthorizedError, NotFoundError, ConflictError, ForbiddenError, Order> result = ComplexOp(id);
// OneOf<T1, T2, T3, T4, T5, T6, T7> — seven-way outcome (v1.39.0+)
// OneOf<T1, T2, T3, T4, T5, T6, T7, T8> — eight-way outcome (v1.39.0+)
⚠️ v1.39.0 — Breaking change:
OneOf<T1..T8>converted fromreadonly structtosealed class. Copy semantics → reference semantics.default(OneOf<T1,T2>)now returnsnull. Nullable reference types (already enabled) flag unsafe callsites at compile time.
Chain extension methods convert between adjacent arities:
// Up-convert: add a new type slot (anchors the new type via defaultValue — not used at runtime)
OneOf<ValidationError, NotFoundError, User> three = ...;
OneOf<ValidationError, NotFoundError, User, ConflictError> four = three.ToFourWay(default(ConflictError));
OneOf<ValidationError, NotFoundError, User, ConflictError, ForbiddenError> five = four.ToFiveWay(default(ForbiddenError));
// Down-convert: narrows to lower arity — returns null if the dropped type slot was active
OneOf<ValidationError, NotFoundError, User>? narrowed = four.ToThreeWay();