This lab note is intentionally incomplete.

Question

Can a small enum specification be enough source material to generate a richer, safer enumeration type without forcing every call site to carry the boilerplate?

The current experiment lives in Ifx.Generators. The concrete usage is IsRecoverableErrorSpecification, which marks a small internal enum with GenerateEnumeration("IsRecoverableError").

[GenerateEnumeration("IsRecoverableError")]
internal enum IsRecoverableErrorSpecification
{
    No,
    Yes
}

That input is deliberately plain. The experiment is about whether the generator can preserve that plainness while producing a type that is better suited for domain code.

Setup

Draft notes:

  • Explain the difference between a plain C# enum and the generated enumeration class.
  • Describe why IsRecoverableError is a useful first example: it is small, binary, and meaningful in error-handling code.
  • Keep the generator discussion focused on behavior, not Roslyn internals for their own sake.
  • Show the generator contract through the attribute: class name, optional default name, namespace, and enumeration base type.

Observation

Draft notes:

  • The generator reads enum members and emits a sealed class with static readonly instances.
  • It creates an All collection for enumeration and lookup.
  • It creates FromValue and FromName helpers that fall back to a default value.
  • The first enum member becomes the default unless another default is supplied.
  • The generated type has equality behavior based on the underlying identifier.

The useful pressure is visible immediately: a tiny source declaration produces a more expressive type, but it also hides generated behavior behind convention. That tradeoff needs to be worth it.

Interpretation

Draft notes:

  • This is not about avoiding a few lines of code. It is about keeping repeated domain patterns consistent.
  • A generator is justified when the boilerplate encodes a rule that should not drift across hand-written implementations.
  • The risk is that generated code can make a simple concept feel more magical than it is.
  • The design should make the input obvious, the output predictable, and the failure modes easy to inspect.

Next Experiment

Draft notes:

  • Decide whether generated lookup should return a default value or expose failure explicitly.
  • Add tests that verify generated output for default selection, member values, FromName, FromValue, and equality.
  • Consider whether the generated type should support case-insensitive name matching.
  • Verify the attribute defaults after the namespace cleanup is complete.
  • Decide whether this pattern belongs only in Ifx or should be documented as a broader coding convention.

Lessons So Far

Draft notes:

  • Source generators are most useful when they remove repetition from a pattern that already has clear rules.
  • The input should stay boring.
  • The generated output should be easy to reason about without opening the generator every time.
  • Code generation is a design commitment, not just a convenience.